二维线段树被卡M+T。。。于是去学二维树状数组区间更新区间查询
树状数组维护数列区间xor的修改、删除(就是把原问题改成一维):
以下p*i实际都指i个p相xor,即(i&1)*p
a表示原数列
d[i]表示a[i]^a[i-1],e[i]=d[i]*i
getd(x)和gete(x)分别表示对d/e求前x个元素的前缀xor
用树状数组维护e[i]和d[i]的前缀xor
区间更新[l,r],x:d[l]^=x,d[r+1]^=x,e[l]^=l*x,e[r+1]^=(r+1)*x
区间查询a[x]的前缀xor:((x+1)*getd(x))^gete(x)
改到二维上,就是树套树,直接套上去就行了。。。没仔细想为什么可以
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 typedef long long LL; 5 int n; 6 #define lowbit(x) ((x)&(-x)) 7 struct Y 8 { 9 LL d[1010],e[1010]; 10 void _add(int p,LL x,LL d[]) 11 { 12 for(;p<=n;p+=lowbit(p)) d[p]^=x; 13 } 14 LL _sum(int p,LL d[]) 15 { 16 LL ans=0; 17 for(;p>0;p-=lowbit(p)) ans^=d[p]; 18 return ans; 19 } 20 void add(int l,int r,LL x) 21 { 22 _add(l,x,d);_add(r+1,x,d); 23 _add(l,(l&1)*x,e);_add(r+1,((r+1)&1)*x,e); 24 } 25 LL sum(int l) 26 { 27 return (((l+1)&1)*_sum(l,d))^_sum(l,e); 28 } 29 }y; 30 struct X 31 { 32 Y d[1010],e[1010]; 33 void _add(int p,int y1,int y2,LL x,Y d[]) 34 { 35 for(;p<=n;p+=lowbit(p)) d[p].add(y1,y2,x); 36 } 37 LL _sum(int p,int y1,int y2,Y d[]) 38 { 39 LL ans=0; 40 for(;p>0;p-=lowbit(p)) ans^=(d[p].sum(y2)^d[p].sum(y1-1)); 41 return ans; 42 } 43 void add(int l,int r,int y1,int y2,LL x) 44 { 45 _add(l,y1,y2,x,d);_add(r+1,y1,y2,x,d); 46 _add(l,y1,y2,(l&1)*x,e);_add(r+1,y1,y2,((r+1)&1)*x,e); 47 } 48 LL sum(int l,int y1,int y2) 49 { 50 return (((l+1)&1)*_sum(l,y1,y2,d))^_sum(l,y1,y2,e); 51 } 52 }x; 53 int m; 54 int main() 55 { 56 int i,a,b,c,d,idx;LL e; 57 scanf("%d%d",&n,&m); 58 for(i=1;i<=m;i++) 59 { 60 scanf("%d",&idx); 61 if(idx==1) 62 { 63 scanf("%d%d%d%d",&a,&b,&c,&d); 64 printf("%lld ",x.sum(c,b,d)^x.sum(a-1,b,d)); 65 } 66 else 67 { 68 scanf("%d%d%d%d%lld",&a,&b,&c,&d,&e); 69 x.add(a,c,b,d,e); 70 } 71 } 72 return 0; 73 }