5301: [Cqoi2018]异或序列
Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 117 Solved: 88
[ Submit][ Status][ Discuss]
Description
已知一个长度为 n 的整数数列 a[1],a[2],…,a[n] ,给定查询参数 l、r ,问在 [l,r] 区间内,有多少连续子
序列满足异或和等于 k 。
也就是说,对于所有的 x,y (l≤x≤y≤r),能够满足a[x]^a[x+1]^…^a[y]=k的x,y有多少组。
Input
输入文件第一行,为3个整数n,m,k。
第二行为空格分开的n个整数,即ai,a2,….an。
接下来m行,每行两个整数lj,rj,表示一次查询。
1≤n,m≤105,O≤k,ai≤105,1≤lj≤rj≤n
Output
输出文件共m行,对应每个查询的计算结果。
Sample Input
4 5 1
1 2 3 1
1 4
1 3
2 3
2 4
4 4
1 2 3 1
1 4
1 3
2 3
2 4
4 4
Sample Output
4
2
1
2
1
2
1
2
1
HINT
Source
这题范围是1e5。
连续异或和,一般考虑保存异或前缀和。区间静态操作题,考虑写一手莫队。
异或真是个神奇的东西。若a^b=c,则a^c=b且b^c=a。
定义cnt[i]为当前区间值为i的前缀的数量(这正是a的值域≤1e5的用意),那我们更新答案时就可以O(1)计算每个增加(删除)节点的贡献。
Code留坑。
/************************************************************** Problem: 5301 User: LoveOI Language: C++ Result: Accepted Time:1568 ms Memory:5200 kb ****************************************************************/ #include <cstdio> #include <cmath> #include <algorithm> #define N 100010 using namespace std; inline char gc() { static char now[1<<16], *S, *T; if(S == T) {T = (S = now) + fread(now, 1, 1<<16, stdin); if(S == T) return EOF;} return *S++; } inline int read() { int x = 0; char c = gc(); while(c < '0' || c > '9') c = gc(); while(c >= '0' && c <= '9') {x = x * 10 + c - 48; c = gc();} return x; } inline void print(long long x) { if(!x) {puts("0"); return ;} int dgt[30], now = -1; while(x) {dgt[++now] = (int)x % 10; x/= 10;} for(int i = now; i >= 0; --i) putchar('0' + dgt[i]); puts(""); } int n, m, k; long long a[N], blank, s[N], answer[N], cnt[N]; struct node {int l, r, id;}q[N]; inline bool cmp1(node A, node B) { int b1 = (A.l - 1)/blank, b2 = (B.l - 1)/blank; if(b1 == b2) return (b1&1)?(A.r<B.r):(A.r > B.r); return b1 < b2; } int main() { n = read(); m = read(); k = read(); for(int i = 1; i <= n; ++i) a[i] = read(); s[0] = 0; for(int i = 1; i <= n; ++i) s[i] = s[i - 1] ^ a[i]; for(int i = 1; i <= m; ++i) {q[i].l = read(); q[i].r = read(); q[i].id = i;} blank = (int)sqrt(n); sort(q+1, q+m+1, cmp1); int l = 1, r = 0; long long ans = 0; for(int i = 1; i <= m; ++i) { while(l < q[i].l - 1) {--cnt[s[l]]; ans-= cnt[k^s[l]]; ++l;} while(l > q[i].l - 1) {--l; ans+= cnt[k^s[l]]; ++cnt[s[l]];} while(r < q[i].r) {++r; ans+= cnt[k^s[r]]; ++cnt[s[r]];} while(r > q[i].r) {--cnt[s[r]]; ans-= cnt[k^s[r]]; --r;} answer[q[i].id] = ans; } for(int i = 1; i <= m; ++i) print(answer[i]); return 0; }