题目链接: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;
}