1 条题解

  • 0
    @ 2026-10-26 15:31:29

    思路与算法

    对Y的每个前缀建立31层持久化二进制Trie,节点保存子树元素个数。一次询问为每个X[u..d]维护Y[l..r]的两个版本游标。从最高位向下,先统计所有游标中使异或当前位为1的元素总数;若不少于k则答案置1并进入相反位,否则扣去该数量并进入同位。每位同时更新全部游标。

    正确性说明

    版本差精确给出当前Y区间里某个二进制前缀的出现次数,重复数也逐个计数。高位不同的异或值大小已确定,故把全部候选按本位1/0分组,按秩选择整组不会排除第k大。逐位归纳,最终得到所求值。

    复杂度

    建Trie初始化和复制O(31M),空间O(31M+N)。每次询问游标初始化O(d-u+1),31轮各扫描该长度,总O(31(d-u+1));总时间O(31M+31PN),计数使用64位。

    易错点

    输入元素小于2^31,只读位30到0。k是第k大而非第k小;必须保留重数。最多3亿矩阵位置,不能实际构造矩阵。

    参考代码(C++11)

    #include <bits/stdc++.h>
    using namespace std;
    struct Node {
        int a[2], cnt;
        Node() {
            a[0] = a[1] = cnt = 0;
        }
    };
    int main() {
        int n, m;
        cin >> n >> m;
        vector<int> x(n), y(m), root(m + 1);
        for (int &v : x)
            cin >> v;
        for (int &v : y)
            cin >> v;
        vector<Node> tr(1);
        tr.reserve((size_t)m * 32 + 1);
        for (int i = 1; i <= m; i++) {
            root[i] = tr.size();
            tr.push_back(tr[root[i - 1]]);
            int u = root[i], v = root[i - 1];
            tr[u].cnt++;
            for (int b = 30; b >= 0; b--) {
                int z = (y[i - 1] >> b) & 1;
                tr[u].a[z] = tr.size();
                tr.push_back(tr[tr[v].a[z]]);
                u = tr[u].a[z];
                v = tr[v].a[z];
                tr[u].cnt++;
            }
        }
        int q;
        cin >> q;
        while (q--) {
            int u, d, l, r;
            long long k;
            cin >> u >> d >> l >> r >> k;
            vector<int> a(d - u + 1, root[r]), b(d - u + 1, root[l - 1]);
            int ans = 0;
            for (int bit = 30; bit >= 0; bit--) {
                long long c = 0;
                for (int i = u - 1; i < d; i++) {
                    int z = ((x[i] >> bit) & 1) ^ 1, j = i - u + 1;
                    c += tr[tr[a[j]].a[z]].cnt - tr[tr[b[j]].a[z]].cnt;
                }
                int want = c >= k;
                if (want)
                    ans |= 1 << bit;
                else
                    k -= c;
                for (int i = u - 1; i < d; i++) {
                    int z = ((x[i] >> bit) & 1) ^ want, j = i - u + 1;
                    a[j] = tr[a[j]].a[z];
                    b[j] = tr[b[j]].a[z];
                }
            }
            cout << ans << '\n';
        }
    }
    
    • 1

    信息

    ID
    1787
    时间
    2000ms
    内存
    512MiB
    难度
    提高
    标签
    递交数
    1
    已通过
    1
    上传者