蒟蒻没看题解yy的思路:因为是异或,所以可以按位统计贡献,于是设x[i]为区间内第i为1的个数,sum为和,tag[i]为异或的第i位的lazytag。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e5+15;
int n,m,arr[N],now[20];
ll a[N][20];
struct Tree{
int l,r;
ll x[20],sum,tag[20];
Tree(){
l=r=sum=0;
memset(tag,0,sizeof(tag));
memset(x,0,sizeof(x));
}
}tr[N<<2];
inline int read(){
int w=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-') f=-1;
ch=getchar();
}
while('0'<=ch&&ch<='9'){
w=w*10+ch-'0';
ch=getchar();
}
return w*f;
}
inline void write(int x){
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
}
inline void pre(int now,int x){
int j = 21;
while(x>0){
a[now][--j]=(x&1);
x>>=1;
}
}
inline void pushup(Tree &fa,Tree &ls,Tree &rs){
for(int i = 0 ; i<20 ; i++) fa.x[i]=ls.x[i]+rs.x[i];
fa.sum=ls.sum+rs.sum;
}
inline void pushdown(Tree &fa,Tree &ls,Tree &rs){
ls.sum=0,rs.sum=0;
for(int i = 0 ; i<20 ; i++){
int tmp=fa.tag[i];
if(tmp){
ls.x[i]=ls.r-ls.l+1-ls.x[i];
rs.x[i]=rs.r-rs.l+1-rs.x[i];
}
ls.sum+=ls.x[i];
rs.sum+=rs.x[i];
ls.tag[i]=tmp,rs.tag[i]=tmp;
fa.tag[i]=0;
}
return ;
}
void build(int id,int l,int r){
tr[id].l=l,tr[id].r=r,tr[id].sum=0;
if(l==r){
for(int i = 0 ; i<20 ; i++)
tr[id].x[i]=a[l][i];
tr[id].sum=arr[l];
return ;
}
int mid=l+r>>1;
build(id<<1,l,mid);
build(id<<1|1,mid+1,r);
pushup(tr[id],tr[id<<1],tr[id<<1|1]);
}
void modify(int id,int x,int y,int k){
int l=tr[id].l,r=tr[id].r;
if(x<=l&&r<=y){
int len=r-l+1;
tr[id].sum=0;
for(int i = 0 ; i<20 ; i++){
if(now[i])
tr[id].x[i]=len-tr[id].x[i];
tr[id].tag[i]^=now[i];
tr[id].sum+=tr[id].x[i];
}
}
pushdown(tr[id],tr[id<<1],tr[id<<1|1]);
int mid=l+r>>1;
if(x<=mid) modify(id<<1,x,y,k);
if(y>mid) modify(id<<1|1,x,y,k);
pushup(tr[id],tr[id<<1],tr[id<<1|1]);
}
ll query(int id,int x,int y){
int l=tr[id].l,r=tr[id].r;
if(x<=l&&r<=y){
return tr[id].sum;
}
pushdown(tr[id],tr[id<<1],tr[id<<1|1]);
int mid=l+r>>1;
long long ret=0;
if(x<=mid) ret+=query(id<<1,x,y);
if(y>mid) ret+=query(id<<1|1,x,y);
return ret;
}
int main(){
n=read();
for(int i = 1 ; i<=n ; i++){
arr[i] = read();
pre(i,arr[i]);
}
build(1,1,n);
m=read();
for(int i = 1 ; i<=m ; i++){
int op=read(),l=read(),r=read();
if(op==1){
write(query(1,l,r));
putchar('\n');
}
else{
memset(now,0,sizeof(now));
int x=read();
int j = 21;
while(x>0){
now[--j]=(x&1);
x>>=1;
}
modify(1,l,r,x);
}
}
return 0;
}