观察什么时候x到y之间那一段可以被统计
xorsum[x-1]^xorsum[y]=k
xorsum[x-1]=xorsum[y]^k||xorsum[y]=xorsum[x-1]^k
莫队维护。
#include<cstdio> #include<cstring> #include<algorithm> #include<cctype> #include<cstdlib> #include<cmath> #define maxn 200200 using namespace std; inline long long read(){ long long num=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch==‘-‘) f=-1; ch=getchar(); } while(isdigit(ch)){ num=num*10+ch-‘0‘; ch=getchar(); } return num*f; } int blo[maxn]; int xum[maxn]; int sum[maxn]; long long ans[maxn]; struct Que{ int x,y,id; bool operator <(const Que a)const{ if(blo[x]!=blo[a.x]) return blo[x]<blo[a.x]; return y<a.y; } }q[maxn]; int main(){ int n=read(),m=read(),e=read(); int sqt=sqrt(n); for(int i=1;i<=n;++i) blo[i]=(i-1)/sqt+1; for(int i=1;i<=n;++i) xum[i]=xum[i-1]^read(); for(int i=1;i<=m;++i) q[i]=(Que){read(),read(),i}; sort(q+1,q+m+1); int lef=1,rig=0;long long now=0; for(int i=1;i<=m;++i){ while(lef<q[i].x-1){ sum[xum[lef]]--; now-=sum[xum[lef]^e]; lef++; } while(lef>q[i].x-1){ lef--; now+=sum[xum[lef]^e]; sum[xum[lef]]++; } while(rig<q[i].y){ rig++; now+=sum[xum[rig]^e]; sum[xum[rig]]++; } while(rig>q[i].y){ sum[xum[rig]]--; now-=sum[xum[rig]^e]; rig--; } ans[q[i].id]=now; } for(int i=1;i<=m;++i) printf("%lld\n",ans[i]); return 0; }
原文地址:https://www.cnblogs.com/cellular-automaton/p/8886315.html
时间: 2024-09-29 23:43:31