Codeforces 242 E. XOR on Segment

题目链接:http://codeforces.com/problemset/problem/242/E


 

线段树要求支持区间求和,区间内每一个数字异或上一个值。

 

  既然是异或,考虑每一个节点维护一个长度为$21*2$的数组${c[x][w][0,1]}$,表示这个节点的子树所包含的线段的点中,这个$2$进制位置上的为$0$和为$1$的分别有多少个。那么一次异或操作其实就是交换了这个位置上的0,1的个数。线段树普通做就可以了。

 

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<vector>
  5 #include<cstdlib>
  6 #include<cmath>
  7 #include<cstring>
  8 using namespace std;
  9 #define maxn 400100
 10 #define llg long long
 11 #define SIZE 22 
 12 #define yyj(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
 13 llg n,m,c[maxn][SIZE][2],xorv[maxn],cnt,T;
 14 llg ans;
 15 
 16 inline int getint()
 17 {
 18        int w=0,q=0; char c=getchar();
 19        while((c<'0' || c>'9') && c!='-') c=getchar(); if(c=='-') q=1,c=getchar(); 
 20        while (c>='0' && c<='9') w=w*10+c-'0', c=getchar(); return q ? -w : w;
 21 }
 22 
 23 void update(llg o)
 24 {
 25     llg lc=o<<1,rc=o<<1|1;
 26     for (llg i=0;i<SIZE;i++) c[o][i][0]=c[lc][i][0]+c[rc][i][0],c[o][i][1]=c[lc][i][1]+c[rc][i][1];
 27 }
 28 
 29 void setv(llg o,llg val)
 30 {
 31     llg wz=0;
 32     while (wz<SIZE)
 33     {
 34         if (val&1) c[o][wz][1]++; else c[o][wz][0]++;
 35         val/=2;
 36         wz++;
 37     }
 38 }
 39 
 40 void xor_(llg o,llg val)
 41 {
 42     llg wz=0;
 43     while (val)
 44     {
 45         if (val&1) swap(c[o][wz][0],c[o][wz][1]);
 46         val/=2;
 47         wz++;
 48     }
 49 }
 50 
 51 void pushdown(llg o,llg l,llg r)
 52 {
 53     llg lc=o<<1,rc=o<<1|1;
 54     if (l==r) return ;
 55     if (xorv[o])
 56     {
 57         xor_(lc,xorv[o]); xor_(rc,xorv[o]);
 58         xorv[lc]^=xorv[o]; xorv[rc]^=xorv[o];
 59         xorv[o]=0;
 60     }
 61 }
 62 
 63 void build(llg o,llg l,llg r)
 64 {
 65     if (l==r)
 66     {
 67         llg x=getint();
 68         setv(o,x);
 69         return ;
 70     }
 71     llg lc=o<<1,rc=o<<1|1,mid=(l+r)>>1;
 72     build(lc,l,mid); build(rc,mid+1,r);
 73     update(o);
 74 }
 75 
 76 void X(llg o,llg l,llg r,llg L,llg R,llg v)
 77 {
 78     pushdown(o,l,r);
 79     if (l>=L && r<=R)
 80     {
 81         xorv[o]^=v;
 82         xor_(o,v);
 83         return ;
 84     }
 85     llg lc=o<<1,rc=o<<1|1,mid=(l+r)>>1;
 86     if (mid>=L) X(lc,l,mid,L,R,v);
 87     if (R>mid) X(rc,mid+1,r,L,R,v);
 88     update(o);
 89 }
 90 
 91 void sum(llg o,llg l,llg r,llg L,llg R)
 92 {
 93     pushdown(o,l,r);
 94     if (l>=L && r<=R)
 95     {
 96         for (llg i=0;i<SIZE;i++) ans+=(1<<i)*c[o][i][1];
 97         return ;
 98     }
 99     llg lc=o<<1,rc=o<<1|1,mid=(l+r)>>1;
100     if (mid>=L) sum(lc,l,mid,L,R);
101     if (R>mid) sum(rc,mid+1,r,L,R);
102     update(o);
103 }
104 
105 int main()
106 {
107     yyj("seg");
108     cin>>n;
109     build(1,1,n);
110     cin>>T;
111     while (T--)
112     {
113         ans=0;
114         llg x,y,z,type;
115         type=getint();
116         if (type==1)
117         {
118             x=getint(),y=getint(),ans=0;
119             sum(1,1,n,x,y);
120             printf("%lld\n",ans);
121         }
122         else
123         {
124             x=getint(),y=getint(),z=getint();
125             X(1,1,n,x,y,z);
126         }
127     }
128     return 0;
129 }

 

posted @ 2017-03-15 16:06  №〓→龙光←  阅读(180)  评论(0编辑  收藏  举报