可以看出來兩人的遊戲是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;
}