242E.XOR on segment(线段树维护区间异或)
Posted 绿憨憨
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了242E.XOR on segment(线段树维护区间异或)相关的知识,希望对你有一定的参考价值。
#include<bits/stdc++.h>
using namespace std;
inline int read()
{
int x=0,f=1;char c=getchar();
while(c<\'0\'||c>\'9\') {if(c==\'-\') f=-1;c=getchar();}
while (c>=\'0\'&&c<=\'9\') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*f;
}
const int maxn=2e5+100;
int a[maxn];
int n,m,tot;
long long c[maxn<<2][30],lz[maxn<<2];
void build (int i,int l,int r) {
if (l==r) {
int bit=0;
while (a[l]) {
c[i][bit]+=a[l]%2;
c[i][bit]%=2;
a[l]/=2;
bit++;
}
return;
}
int mid=(l+r)>>1;
build(i<<1,l,mid);
build(i<<1|1,mid+1,r);
for (int j=0;j<=20;j++) c[i][j]=c[i<<1][j]+c[i<<1|1][j];
}
void spread (int i,int l,int r) {
int mid=(l+r)>>1;
if (lz[i]) {
lz[i<<1]^=lz[i];
lz[i<<1|1]^=lz[i];
int bit=0;
while (lz[i]) {
int x=lz[i]%2;
lz[i]/=2;
if (x==1) c[i<<1][bit]=mid-l+1-c[i<<1][bit],c[i<<1|1][bit]=r-mid-c[i<<1|1][bit];
bit++;
}
}
}
void up (int i,int l,int r,int L,int R,int x) {
//这个区间的数与
if (l>=L&&r<=R) {
lz[i]^=x;
int bit=0;
while (x) {
int y=x%2;
x/=2;
if (y) c[i][bit]=r-l+1-c[i][bit];
bit++;
}
return;
}
spread(i,l,r);
int mid=(l+r)>>1;
if (L<=mid) up(i<<1,l,mid,L,R,x);
if (R>mid) up(i<<1|1,mid+1,r,L,R,x);
for (int j=0;j<=20;j++) c[i][j]=c[i<<1][j]+c[i<<1|1][j];
}
long long query (int i,int l,int r,int L,int R) {
if (l>=L&&r<=R) {
long long bit=1;
long long ans=0;
for (int j=0;j<=20;j++) {
ans+=c[i][j]*bit;
bit*=2;
}
return ans;
}
spread(i,l,r);
int mid=(l+r)>>1;
long long ans=0;
if (L<=mid) ans+=query(i<<1,l,mid,L,R);
if (R>mid) ans+=query(i<<1|1,mid+1,r,L,R);
return ans;
}
int main () {
n=read();
for (int i=1;i<=n;i++) a[i]=read();
build(1,1,n);
m=read();
while (m--) {
int op;
op=read();
if (op==1) {
int l=read(),r=read();
printf("%lld\\n",query(1,1,n,l,r));
}
else {
int l=read();
int r=read();
int x=read();
up(1,1,n,l,r,x);
}
}
}
以上是关于242E.XOR on segment(线段树维护区间异或)的主要内容,如果未能解决你的问题,请参考以下文章