「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\n", ans[i]);
return 0;
}
原文地址:https://www.cnblogs.com/15owzLy1-yiylcy/p/10518315.html
时间: 2024-11-07 23:49:42