Codeforces 617E XOR and Favorite Number(莫队算法)
题目大概说给一个序列,多次询问区间异或和为k的连续子序列有多少个。
莫队算法,利用异或的性质,通过前缀和求区间和,先处理出序列各个前缀和,然后每次区间转移时维护i以及i-1前缀和为某数的个数并增加或减少对答案的贡献。
1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<algorithm> 5 using namespace std; 6 #define MAXN (1<<20) 7 8 int block; 9 struct Query{ 10 int l,r,i; 11 bool operator<(const Query &q) const { 12 if(l/block==q.l/block) return r<q.r; 13 return l/block<q.l/block; 14 } 15 }query[111111]; 16 17 int n,m,k,a[111111],sum[111111]; 18 19 int cnt1[MAXN],cnt2[MAXN]; 20 long long ans; 21 void left_insert(int i){ 22 ++cnt1[sum[i-1]]; 23 ++cnt2[sum[i]]; 24 ans+=cnt2[sum[i-1]^k]; 25 } 26 void left_remove(int i){ 27 ans-=cnt2[sum[i-1]^k]; 28 --cnt1[sum[i-1]]; 29 --cnt2[sum[i]]; 30 } 31 void right_insert(int i){ 32 ++cnt1[sum[i-1]]; 33 ++cnt2[sum[i]]; 34 ans+=cnt1[sum[i]^k]; 35 } 36 void right_remove(int i){ 37 ans-=cnt1[sum[i]^k]; 38 --cnt1[sum[i-1]]; 39 --cnt2[sum[i]]; 40 } 41 42 long long res[111111]; 43 44 int main(){ 45 scanf("%d%d%d",&n,&m,&k); 46 for(int i=1; i<=n; ++i){ 47 scanf("%d",a+i); 48 sum[i]=sum[i-1]^a[i]; 49 } 50 for(int i=0; i<m; ++i){ 51 scanf("%d%d",&query[i].l,&query[i].r); 52 query[i].i=i; 53 } 54 55 block=(int)(sqrt(n)+1e-6); 56 sort(query,query+m); 57 58 int l=1,r=1; 59 right_insert(1); 60 for(int i=0; i<m; ++i){ 61 while(l<query[i].l) left_remove(l++); 62 while(l>query[i].l) left_insert(--l); 63 while(r<query[i].r) right_insert(++r); 64 while(r>query[i].r) right_remove(r--); 65 res[query[i].i]=ans; 66 } 67 68 for(int i=0; i<m; ++i){ 69 printf("%lld\n",res[i]); 70 } 71 return 0; 72 }