CF 242E XOR on Segment

来源:互联网 发布:知乎德国白啤酒 编辑:程序博客网 时间:2024/09/21 08:16

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


题目大意:

给定一个长为n(n<=10^5)的数组,数组里的数不超过10^6,有两种操作

1:求sum[l,r];       2:对[l,r]中的所有数和x异或


题目思路:

一看题目,摆明了是成段更新的线段树,但是异或不符合分配律的( (a+b)^x != a^x+b^x ),但是我们知道异或对于一个数上的二进制表达式的所有位是独立的,又知道数组中的数不超过10^6,二进制大概是20位,所以我们线段树就维护该段中所有数的某一位上有几个1和0即可.


代码:

#include <stdlib.h>#include <string.h>#include <stdio.h>#include <ctype.h>#include <math.h>#include <stack>#include <queue>#include <map>#include <set>#include <vector>#include <string>#include <iostream>#include <algorithm>using namespace std;#define ll long long#define ls rt<<1#define rs ls|1#define lson l,mid,ls#define rson mid+1,r,rs#define middle (l+r)>>1#define eps (1e-9)#define type int#define clr_all(x,c) memset(x,c,sizeof(x))#define clr(x,c,n) memset(x,c,sizeof(x[0])*(n+1))#define MOD 1000000007#define inf 0x3f3f3f3f#define pi acos(-1.0)#define _max(x,y) (((x)>(y))? (x):(y))#define _min(x,y) (((x)<(y))? (x):(y))#define _abs(x) ((x)<0? (-(x)):(x))#define getmin(x,y) (x= (x==-1 || (y)<x)? (y):x)#define getmax(x,y) (x= ((y)>x)? (y):x)template <class T> void _swap(T &x,T &y){T t=x;x=y;y=t;}int TS,cas;const int M=100000+5;int n,m;int sum[M<<2][20][2],cov[M<<2],ret[20];void pushUp(int rt){for(int i=0;i<20;i++)for(int j=0;j<2;j++)sum[rt][i][j]=sum[ls][i][j]+sum[rs][i][j];}void build(int l,int r,int rt){if(l==r){int a;scanf("%d",&a);clr_all(sum[rt],0),cov[rt]=0;for(int i=0;i<20;i++,a/=2)sum[rt][i][a&1]++;return;}int mid=middle;build(lson),build(rson);pushUp(rt);}void pushDown(int rt){if(!cov[rt]) return;cov[ls]^=cov[rt],cov[rs]^=cov[rt];for(int i=0;cov[rt];i++,cov[rt]/=2) if(cov[rt]&1){_swap(sum[ls][i][0],sum[ls][i][1]);_swap(sum[rs][i][0],sum[rs][i][1]);}}void update(int l,int r,int rt,int L,int R,int c){if(L<=l && r<=R){cov[rt]^=c;int i;for(i=0;c;i++,c/=2) if(c&1)_swap(sum[rt][i][0],sum[rt][i][1]);return;}pushDown(rt);int mid=middle;if(L<=mid) update(lson,L,R,c);if(mid<R) update(rson,L,R,c);pushUp(rt);}void query(int l,int r,int rt,int L,int R){if(L<=l && r<=R){for(int i=0;i<20;i++)ret[i]+=sum[rt][i][1];return;}pushDown(rt);int mid=middle;if(L<=mid) query(lson,L,R);if(mid<R) query(rson,L,R);}void run(){int i,j;build(1,n,1);scanf("%d",&m);int t,l,r,x;while(m--){scanf("%d%d%d",&t,&l,&r);if(t==1){clr_all(ret,0);query(1,n,1,l,r);ll ans=0,g=0,pw2=1,c;for(i=0;i<20 || g;i++,pw2*=2){c=g+((i<20)? ll(ret[i]):0);ans+=(c%2)*pw2;g=c/2;}printf("%I64d\n",ans);}else{scanf("%d",&x);update(1,n,1,l,r,x);}}}void preSof(){}int main(){//freopen("input.txt","r",stdin);//freopen("output.txt","w",stdout);preSof();//run();while(~scanf("%d",&n)) run();//for(scanf("%d",&TS),cas=1;cas<=TS;cas++) run();return 0;}