1. 程式人生 > >Iahub and Xors Codeforces - 341D

Iahub and Xors Codeforces - 341D

++ get += ORC clas 樹套樹 efi 維護 \n

二維線段樹被卡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\n",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 }

Iahub and Xors Codeforces - 341D