可以看出来两人的游戏是nim博弈 所以如果区间内的数异或和不为0 那么Alice 必胜
简单分析一下我们肯定要做一个前缀异或 然后再莫队就行 因为Bob会对序列进行修改 所以我们需要用带修莫队 然后就变成一个板子题目了
带修莫队 在块大小为 n^(2/3) 理论上复杂度最优
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N = 1e5+10,M = 1e6+100; typedef long long ll; int xsum[N],p[N],sqn,a[N],blk; ll tx[M],ans[N],ret; struct node{ int l,r,t,id; bool operator < (const node &a)const{ if(l/blk!=a.l/blk) return l/blk<a.l/blk; if(r/blk!=a.r/blk) return r/blk<a.r/blk; return t<a.t; } }q[N]; void add(int x){ret+=tx[xsum[x]]++;} void del(int x){ret-=--tx[xsum[x]];} void upd(int i,int t){ int flag=(p[t]<=q[i].r&&p[t]>=q[i].l); if(flag) del(p[t]); xsum[p[t]]^=a[p[t]],swap(a[p[t]],a[p[t]+1]),xsum[p[t]]^=a[p[t]]; //printf("xsum=%d\n",xsum[p[t]]); if(flag) add(p[t]); } int main(){ int n,m; while(~scanf("%d%d",&n,&m)){ memset(tx,0,sizeof(tx)); ret=0; blk=max(10,(int)pow(n,2./3)); int qcnt=0,kcnt=0; for(int i = 1; i <= n; i++){ scanf("%d",&a[i]); xsum[i]=xsum[i-1]^a[i]; } for(int i = 1; i <= m; i++){ int op,l,r; scanf("%d%d",&op,&l); if(op==1){ scanf("%d",&r); q[++qcnt]=(node){l-1,r,kcnt,qcnt}; } else p[++kcnt]=l; } sort(q+1,q+1+qcnt); int l=1,r=0,T=0; for(int i = 1; i <= qcnt; i++){ while(l<q[i].l) del(l++); while(l>q[i].l) add(--l); while(r<q[i].r) add(++r); while(r>q[i].r) del(r--); while(T<q[i].t) upd(i,++T); while(T>q[i].t) upd(i,T--); ans[q[i].id]=1ll*(q[i].r-q[i].l)*(q[i].r-q[i].l+1)/2ll-ret; } for(int i = 1; i <= qcnt; i++) printf("%lld\n",ans[i]); } return 0; }