E. XOR and Favorite Number(莫队异或)
题目描述
给定一个长度为 n 的序列 a,然后再给一个数字 k,再给出 m 组询问,每组询问给出一个区间,求这个区间里面有多少个子区间的异或值为 k
1≤n,m≤10^5,0≤k,ai≤10^6,1≤li≤ri≤n
题目思路
要做这个题首先要知道两个性质
1.异或前缀和
2.a^b=x则a^x=b
1.处理出异或前缀和数组a[i]^=a[i-1];
2.对于区间[L,R]的异或和,即为a[R]^a[L-1]
3.如果x ^ y=k,那么x=k ^ y
对于一个区间[L,R],我们维护[L-1,R]的异或前缀和.
当加入新元素时a[x],如果在我们维护的前缀和里存在a[x]^k,那么就会对答案产生贡献.
注意这个题左端点是L-1,这是关键!
#include<iostream> #include<algorithm> using namespace std; typedef long long ll; const int maxn=5e6+100; ll a[maxn],ans[maxn]; const int block=313; struct node{ int l,r,id; bool friend operator<(node x,node y){ if(x.l/block!=y.l/block){ return x.l/block<y.l/block; } else{ if((x.l/block)&1){ return x.r>y.r; } else{ return x.r<y.r; } } } }q[maxn]; ll cnt[maxn]; ll tot=0; int n,m; ll k; inline void add(int p) { tot+=cnt[k^a[p]]; cnt[a[p]]++; } inline void del(int p) { cnt[a[p]]--;//要先减减 tot-=cnt[k^a[p]]; } int main(){ scanf("%d%d%lld",&n,&m,&k); for(int i=1;i<=n;i++){ scanf("%lld",&a[i]); a[i]^=a[i-1]; } for(int i=1;i<=m;i++){ scanf("%d%d",&q[i].l,&q[i].r); q[i].l--; q[i].id=i; } sort(q+1,q+m+1); int ql=q[1].l,qr=q[1].r; for(int i=ql;i<=qr;i++){ add(i); } ans[q[1].id]=tot; for(int i=2;i<=m;i++){ while(ql<q[i].l){ del(ql); ql++; } while(qr>q[i].r){ del(qr); qr--; } while(ql>q[i].l){ ql--; add(ql); } while(qr<q[i].r){ qr++; add(qr); } ans[q[i].id]=tot; } for(int i=1;i<=m;i++){ cout<<ans[i]<<"\n"; } }
#include<iostream> #include<algorithm> using namespace std; typedef long long ll; const int maxn=5e6+100; ll a[maxn],ans[maxn]; const int block=313; struct node{ int l,r,id; bool friend operator<(node x,node y){ if(x.l/block!=y.l/block){ return x.l/block<y.l/block; } else{ if((x.l/block)&1){ return x.r>y.r; } else{ return x.r<y.r; } } } }q[maxn]; ll cnt[maxn]; ll tot=0; int n,m; ll k; inline void add(int p) { tot+=cnt[k^a[p]]; cnt[a[p]]++; } inline void del(int p) { cnt[a[p]]--; tot-=cnt[k^a[p]]; } int main(){ scanf("%d%d%lld",&n,&m,&k); for(int i=1;i<=n;i++){ scanf("%lld",&a[i]); a[i]^=a[i-1]; } for(int i=1;i<=m;i++){ scanf("%d%d",&q[i].l,&q[i].r); q[i].l--; q[i].id=i; } sort(q+1,q+m+1); int ql=0,qr=0; cnt[a[0]]=1; for(int i=1;i<=m;i++){ while(ql<q[i].l){ del(ql); ql++; } while(qr>q[i].r){ del(qr); qr--; } while(ql>q[i].l){ ql--; add(ql); } while(qr<q[i].r){ qr++; add(qr); } ans[q[i].id]=tot; } for(int i=1;i<=m;i++){ cout<<ans[i]<<"\n"; } }