http://codeforces.com/problemset/problem/339/D
给出一个序列。每次更改其中一个值然后询问序列的f(),序列的f()定义为: 每相邻两个元素按位或得到长度减半的序列,在对每相邻两个元素按位异或得到长度再次减半的序列。。。。更替的进行按位或/异或,
直至序列长度为1,输出这个数即可。
op维护当前节点的操作符号,g维护当前区间价值。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define LL long long 4 #define ULL unsigned long long 5 const int maxn=150000; 6 int a[maxn]; 7 class sg_tree 8 { 9 public: 10 #define mid ((L+R)>>1) 11 #define lc (id<<1) 12 #define rc (id<<1|1) 13 14 int N,g[maxn<<2]; 15 bool op[maxn<<2]; 16 17 void build(int id,int L,int R) 18 { 19 if(L==R) 20 { 21 scanf("%d",&g[id]); 22 op[id]=1; 23 return; 24 } 25 build(lc,L,mid); 26 build(rc,mid+1,R); 27 op[id]=(op[lc]^1); 28 if(op[id]==0) g[id]=(g[lc]|g[rc]); 29 else g[id]=(g[lc]^g[rc]); 30 } 31 32 void change(int id,int L,int R,int p,int b) 33 { 34 if(L==R) 35 { 36 g[id]=b; 37 return; 38 } 39 if(p<=mid)change(lc,L,mid,p,b); 40 else change(rc,mid+1,R,p,b); 41 if(op[id]==0) g[id]=(g[lc]|g[rc]); 42 else g[id]=(g[lc]^g[rc]); 43 } 44 } ac; 45 int main() 46 { 47 int n,m,p,b; 48 scanf("%d%d",&n,&m); 49 ac.N=(1<<n); 50 ac.build(1,1,ac.N); 51 while(m--) 52 { 53 scanf("%d%d",&p,&b); 54 ac.change(1,1,ac.N,p,b); 55 printf("%d ",ac.g[1]); 56 } 57 return 0; 58 } 59 /* 60 2 4 61 1 6 3 5 62 1 4 63 3 4 64 1 2 65 1 2 66 67 */