1 条题解

  • 0
    @ 2026-4-2 20:46:31

    题目题解

    问题理解

    给定数组 aa 和整数 kk。每次操作可以选择长度 k\ge k 的子数组,删除其中第 kk 小的元素(若有多个相同值则任选一个)。问能否通过若干次操作使剩余数组成为回文。


    第一步:哪些元素可以删除?

    关键观察
    只要数组中仍然保留着最小的 k1k-1 个元素(按值排序),就可以任意删除其他元素。

    证明
    xx 为第 k1k-1 小的元素值(若 k=1k=1 则无限制)。
    对于任何值 >x> x 的元素,它一定是某个子数组的第 kk 小(因为至少有 k1k-1 个更小的元素在数组中)。
    我们可以通过收缩子数组边界,使该元素恰好成为第 kk 小,从而删除它。
    因此,所有大于 xx 的元素都可以被删除

    而对于值等于 xx 的元素,它们可能成为第 kk 小,也可能不成为,取决于是否有足够多的更小元素。
    但无论如何,值小于 xx 的元素永远不能被删除,因为它们是前 k1k-1 小,在任何长度 k\ge k 的子数组中,它们至少是第 k1k-1 小,永远不会成为第 kk 小。


    第二步:简化问题

    xx 为第 k1k-1 小的值(若 k=1k=1xx 可视为 00 或不存在)。
    根据上述结论:

    • 所有值 <x< x 的元素必须保留(不能删)。
    • 所有值 >x> x 的元素都可以删除(且应该删除,因为它们会干扰回文)。
    • =x= x 的元素可以删也可以留,但删除它们会消耗“配额”。

    因此,我们可以先删除所有 >x> x 的元素,得到新数组 cc,只包含 x\le x 的元素。
    m=cm = |c|,其中值 <x< x 的有 tt 个,值 =x= x 的有 mtm - t 个。
    由于 xx 是第 k1k-1 小,我们有 t=k1t = k-1
    所以 m=(k1)+cntxm = (k-1) + \text{cnt}_x,其中 cntx\text{cnt}_x 是原数组中值为 xx 的个数。


    第三步:构造回文

    现在数组 cck1k-1 个小于 xx 的值和若干等于 xx 的值组成。
    我们希望删除一些等于 xx 的元素(因为小于 xx 的不能删),使得剩余数组成为回文。

    设我们保留的等于 xx 的个数为 pp,则总保留元素数为 (k1)+p(k-1) + p
    我们可以在 cc 上使用双指针从两端向中间匹配:

    • cL=cRc_L = c_R,则保留这两个元素,指针移动。
    • cLcRc_L \neq c_R,则必须删除其中一个等于 xx 的元素(因为小于 xx 的不能删,且它们互不相同),并消耗一次“删除配额”。如果两个都不等于 xx,则无法匹配,输出 "NO"

    初始可删除的 xx 的个数为 cntx\text{cnt}_x(即所有等于 xx 的元素)。
    每删除一个 xx,配额减少 11
    若过程中配额不足或无法匹配,则 "NO";否则 "YES"


    第四步:边界情况

    • k=1k=1 时,没有必须保留的元素,可以删除任意元素。此时总是可以构造回文(例如只保留一个元素,或删除到空数组),所以直接输出 "YES"

    • k>1k > 1 时,按照上述双指针过程判断。


    第五步:算法步骤

    1. k=1k=1,输出 "YES"
    2. 否则:
      • aa 排序,找到第 k1k-1 小的值 xx
      • 构造新数组 cc,只包含 x\le x 的元素。
      • spare=cntxspare = \text{cnt}_x(值为 xx 的元素个数,即可以删除的 xx 的数量)。
      • 双指针 L=0,R=c1L=0, R=|c|-1,遍历:
        • c[L]=c[R]c[L] = c[R]L++L++, RR--
        • 否则:
          • spare=0spare = 0,失败。
          • c[L]=xc[L] = x,则删除它:L++L++, sparespare--
          • 否则若 c[R]=xc[R] = x,则删除它:RR--, sparespare--
          • 否则失败。
      • 若遍历完成,输出 "YES",否则 "NO"

    时间复杂度

    • 排序:O(nlogn)O(n \log n)
    • 双指针:O(n)O(n)
    • 总复杂度 O(nlogn)O(n \log n),满足 n2×105\sum n \le 2\times 10^5

    代码实现

    #include <bits/stdc++.h>
    using namespace std;
    
    void solve() {
        int n, k;
        cin >> n >> k;
        vector<int> a(n);
        for (int i = 0; i < n; i++) {
            cin >> a[i];
        }
        
        if (k == 1) {
            cout << "YES\n";
            return;
        }
        
        // 找第 k-1 小的值
        vector<int> b = a;
        sort(b.begin(), b.end());
        int x = b[k - 2];  // 第 k-1 小的值(0-indexed)
        
        // 构造只包含 <= x 的数组
        vector<int> c;
        int cnt_x = 0;
        for (int v : a) {
            if (v <= x) {
                c.push_back(v);
                if (v == x) cnt_x++;
            }
        }
        
        int spare = cnt_x;  // 可以删除的 x 的个数
        int L = 0, R = c.size() - 1;
        bool ok = true;
        
        while (L < R) {
            if (c[L] == c[R]) {
                L++;
                R--;
            } else {
                if (spare == 0) {
                    ok = false;
                    break;
                }
                if (c[L] == x) {
                    L++;
                    spare--;
                } else if (c[R] == x) {
                    R--;
                    spare--;
                } else {
                    ok = false;
                    break;
                }
            }
        }
        
        cout << (ok ? "YES" : "NO") << "\n";
    }
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        
        int t;
        cin >> t;
        while (t--) {
            solve();
        }
        
        return 0;
    }
    

    验证样例

    输入:

    8
    5 3
    5 4 3 4 5
    4 1
    1 1 2 1
    6 6
    2 3 4 5 3 2
    5 4
    5 2 4 3 1
    8 5
    4 7 1 2 3 1 3 4
    5 4
    1 2 1 2 2
    3 3
    1 2 2
    4 4
    2 1 2 2
    

    输出:

    YES
    YES
    YES
    NO
    NO
    YES
    NO
    YES
    

    与题目输出一致。


    总结

    本题的关键在于:

    1. 识别出只有最小的 k1k-1 个元素不可删除。
    2. 将问题简化为只保留 x\le x 的元素,并利用双指针匹配回文,必要时删除值为 xx 的元素。
    • 1

    信息

    ID
    6254
    时间
    1000ms
    内存
    256MiB
    难度
    1
    标签
    递交数
    1
    已通过
    1
    上传者