http://codeforces.com/contest/617/problem/E
莫队算法,O(n1.5),在数据量1e5的时候还可以使用
主要为研究[l,r]到[l,r+1]的O(1)或O(logn)转移,如能实现,那么就可以AC了
增加了a[r+1]后可以发现,需计算
根据异或和的性质转换后
所以,则在转移前后维护好SUM[L-1]到SUM[R]的哈希表,即可在O(1)得到转移后的结果
代码:
1 #include<stdio.h> 2 #include<algorithm> 3 #include<string.h> 4 #include<map> 5 #include<queue> 6 #include<set> 7 #include<cmath> 8 #include<vector> 9 #define MAXN 1000005 10 using namespace std; 11 typedef long long ll; 12 int a[100005]; 13 struct Edg{ 14 int l,r; 15 int num,pos; 16 ll v; 17 }e[100005]; 18 int b[1500005]={0},sum[1000005]; 19 bool cmp1(struct Edg x,struct Edg y) 20 { if(x.pos==y.pos) return x.r<y.r; 21 return x.l<y.l; 22 } 23 bool cmp2(struct Edg x,struct Edg y) 24 { 25 return x.num<y.num; 26 } 27 int main() 28 { int n,m,k; 29 30 scanf("%d%d%d",&n,&m,&k); 31 for(int i=1;i<=n;i++) 32 { 33 scanf("%d",&a[i]); 34 } 35 sum[0]=0; 36 37 for(int i=1;i<=n;i++) 38 { 39 sum[i]=sum[i-1]^a[i]; 40 } 41 int x=sqrt(n); //注意 42 for(int i=1;i<=m;i++) 43 { 44 scanf("%d%d",&e[i].l,&e[i].r); 45 e[i].num=i,e[i].pos=e[i].l/x; 46 } 47 48 sort(e+1,e+m+1,cmp1); 49 int l=1,r=0; 50 ll temp=0; 51 memset(b,0,sizeof(b)); 52 53 for(int i=1;i<=m;i++) 54 { 55 while(r<e[i].r) 56 { 57 r++; 58 temp+=b[sum[r]^k]; 59 b[sum[r]]++; 60 } 61 while(r>e[i].r) 62 { 63 b[sum[r]]--; 64 temp-=b[sum[r]^k]; 65 r--; 66 } 67 while(l>e[i].l-1) 68 { 69 l--; 70 temp+=b[sum[l]^k]; 71 b[sum[l]]++; 72 } 73 while(l<e[i].l-1) 74 { 75 b[sum[l]]--; 76 temp-=b[sum[l]^k]; 77 l++; 78 } 79 e[i].v=temp; 80 } 81 82 sort(e+1,e+m+1,cmp2); 83 for(int k=1;k<=m;k++) 84 { 85 printf("%lld ",e[k].v); 86 } 87 return 0; 88 }