您的位置:首页 > 其它

Codeforces242E XOR on Segment(线段树)

2016-07-29 19:43 204 查看
Codeforces242E XOR on Segment

题意:

有一个长度为n的数列,给出两种操作:

1.对区间(l,r)求和并输出。

2.对区间(l,r)内的所有数都修改为原来的数异或x后得到的值。

分析:

线段树,延迟标记,区间求和,但维护不能直接维护求和的值,因为有异或操作,所以将数拆成二进制,记录每一位出现的次数,每异或一次,就相当于将区间和各二进制位0变1、1变0,求和计算一下即可。

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <queue>
using namespace std;
typedef long long LL;
typedef double DB;
#define INF 2147483647
#define mms(_x, _y) memset(_x, _y, sizeof(_x));
#define rep(_x, _y, _z) for(int _x = _y; _x <= _z; _x++)
#define per(_x, _y, _z) for(int _x = _y; _x >= _z; _x--)
const int MOD=1e6+3;
const double pi = acos(-1.0);
const double E = exp(1.0);
const int M = 1e5+9;
struct node{
int xo[25];
LL su[25];
}tn[M*4];
int n,m,nu[M],change[25],cl,cr,cx,type,cd;
LL Quick_pow(LL qx, LL qa){
LL qans = 1;
while(qa){
if(qa&1)qans*=qx;
qx*=qx;
qa>>=1;
}
return qans;
}
void Inittree(int rt,int l,int r){
mms(tn[rt].xo,0);
mms(tn[rt].su,0);
if(l==r){
int d=0;
while(nu[l]){
tn[rt].su[d]=nu[l]&1;
nu[l]>>=1;
d++;
}
return;
}
int mid=l+r>>1;
Inittree(rt*2+1,l,mid);
Inittree(rt*2+2,mid+1,r);
rep(i,0,21)tn[rt].su[i]=tn[rt*2+1].su[i]+tn[rt*2+2].su[i];
}
void update(int rt,int l,int r){
if(cl>r||cr<l)return;
if(cl<=l&&cr>=r){
rep(i,0,21)tn[rt].xo[i]+=change[i];
rep(i,0,21)if(change[i])tn[rt].su[i]=r-l+1-tn[rt].su[i];
return;
}
int mid=l+r>>1;
rep(i,0,21){
if(tn[rt].xo[i]%2){
tn[rt*2+1].xo[i]+=1;
tn[rt*2+2].xo[i]+=1;
tn[rt*2+1].su[i]=mid-l+1-tn[rt*2+1].su[i];
tn[rt*2+2].su[i]=r-mid-tn[rt*2+2].su[i];
tn[rt].xo[i]=0;
}
}
update(rt*2+1,l,mid);
update(rt*2+2,mid+1,r);
rep(i,0,21)tn[rt].su[i]=tn[rt*2+1].su[i]+tn[rt*2+2].su[i];
}
LL find(int rt,int l,int r){
LL ans=0;
if(cl>r||cr<l)return 0;
if(cl<=l&&cr>=r){
rep(i,0,21)ans+=tn[rt].su[i]*Quick_pow(2,i);
}
e
4000
lse{
int mid=l+r>>1;
rep(i,0,21){
if(tn[rt].xo[i]%2){
tn[rt*2+1].xo[i]+=1;
tn[rt*2+2].xo[i]+=1;
tn[rt*2+1].su[i]=mid-l+1-tn[rt*2+1].su[i];
tn[rt*2+2].su[i]=r-mid-tn[rt*2+2].su[i];
tn[rt].xo[i]=0;
}
}
ans=find(rt*2+1,l,mid)+find(rt*2+2,mid+1,r);
}
return ans;
}
void Init(){
scanf("%d",&n);
rep(i,1,n)scanf("%d",&nu[i]);
Inittree(0,1,n);
scanf("%d",&m);
}
void Solve(){
while(m--){
scanf("%d%d%d",&type,&cl,&cr);
if(type==1)printf("%I64d\n",find(0,1,n));
else{
scanf("%d",&cx);
mms(change,0);
cd=0;
while(cx){
change[cd]=cx&1;
cx>>=1;
cd++;
}
update(0,1,n);
}
}
}
int main(){
int _T = 1;
//scanf("%d",&_T);
while(_T--){
Init();
Solve();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  线段树