「luogu4462」[CQOI2018] 异或序列

「luogu4462」[CQOI2018]异或序列

一句话题意

输入 (n) 个数,给定(k),共 (m) 组询问,输出第 (i) 组询问 (l_i) (r_i) 中有多少个连续子序列的异或和等于 (k)。数据范围均在 ([0,1e5])

本题不强制在线,故莫队。
记序列 (a) 的前缀异或和 (pre),用一个桶 (t_i) 记录当前查询区间内前缀异或和为 (i) 的数量。

代码如下:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
inline int in() {
    int x=0;char c=getchar();bool f=false;
    while(c<'0'||c>'9') f|=c=='-', c=getchar();
    while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48), c=getchar();
    return f?-x:x;
}

const int N = 1e5+5;

int n, m, k, cur, pre[N], t[N<<1], blo, bl[N], ans[N];

struct query {
    int l, r, id;
    inline friend bool operator < (const query &x, const query &y) {
        return bl[x.l]==bl[y.l]?x.r<y.r:x.l<y.l;
    }
}q[N];

inline void add(int u) {
    cur+=t[u^k];
    t[u]++;
}

inline void rem(int u) {
    t[u]--;
    cur-=t[u^k];
}

int main() {
    n=in(), m=in(), k=in();
    blo=(int)sqrt(n+1);
    for(int i=1;i<=n;++i) {
        bl[i]=(i-1)/blo+1;
        pre[i]=pre[i-1]^in();
    }
    for(int i=1;i<=m;++i) q[i]=(query){in()-1, in(), i};
    std::sort(q+1, q+1+m);

    for(int i=1, l=1, r=0;i<=m;++i) {
        for(;r<q[i].r;add(pre[++r]));
        for(;r>q[i].r;rem(pre[r--]));
        for(;l<q[i].l;rem(pre[l++]));
        for(;l>q[i].l;add(pre[--l]));
        ans[q[i].id]=cur;
    }
    for(int i=1;i<=m;++i) printf("%d
", ans[i]);
    return 0;
}
原文地址:https://www.cnblogs.com/15owzLy1-yiylcy/p/10518315.html