242E:XOR on Segment
题意简述
维护一个长度为
n
的数列,完成
1.询问
[l,r]
的区间和。
2.将
[l,r]
之间的所有数都异或
val
。
数据范围
1≤n≤105
1≤q≤5∗104
1≤ai≤106
思路
线段树维护二进制每一位的个数。
异或操作对某一位来说就是交换它的
0,1
的个数。
维护一个lazy标记。
求和操作就把每一位的贡献合起来。
时间复杂度
O(nlognlog106)
代码
#include<cstdio>
#include<iostream>
using namespace std;
int n,q,u,v,w,opt;
int seq[100010];
namespace Segtree
{
struct Node{
int num[20][2];
int xx;
}tree[400010];
void pushup(int node)
{
for (int i=0;i<20;i++)
{
tree[node].num[i][0]=tree[node<<1].num[i][0]+tree[node<<1|1].num[i][0];
tree[node].num[i][1]=tree[node<<1].num[i][1]+tree[node<<1|1].num[i][1];
}
}
void pushdown(int node)
{
if (tree[node].xx)
{
for (int i=0;i<20;i++)
if (tree[node].xx&(1<<i))
{
swap(tree[node<<1].num[i][0],tree[node<<1].num[i][1]);
swap(tree[node<<1|1].num[i][0],tree[node<<1|1].num[i][1]);
}
tree[node<<1].xx^=tree[node].xx;
tree[node<<1|1].xx^=tree[node].xx;
tree[node].xx=0;
}
}
void modify(int L,int R,int l,int r,int node,int val)
{
if (L<=l&&r<=R)
{
for (int i=0;i<20;i++)
if (val&(1<<i))
swap(tree[node].num[i][0],tree[node].num[i][1]);
tree[node].xx^=val;
return;
}
pushdown(node);
int mid=(l+r)>>1;
if (L<=mid)
modify(L,R,l,mid,node<<1,val);
if (R>mid)
modify(L,R,mid+1,r,node<<1|1,val);
pushup(node);
}
long long query(int L,int R,int l,int r,int node)
{
if (L<=l&&r<=R)
{
long long ret=0;
for (int i=0;i<20;i++)
ret+=(1LL<<i)*tree[node].num[i][1];
return ret;
}
pushdown(node);
long long ret=0;
int mid=(l+r)>>1;
if (L<=mid)
ret+=query(L,R,l,mid,node<<1);
if (R>mid)
ret+=query(L,R,mid+1,r,node<<1|1);
return ret;
}
void build(int l,int r,int node)
{
if (l==r)
{
for (int i=0;i<20;i++)
if (seq[l]&(1<<i))
tree[node].num[i][1]++;
else
tree[node].num[i][0]++;
return;
}
int mid=(l+r)>>1;
build(l,mid,node<<1);
build(mid+1,r,node<<1|1);
pushup(node);
}
}
void init()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
scanf("%d",&seq[i]);
Segtree::build(1,n,1);
}
void work()
{
scanf("%d",&q);
for (int i=1;i<=q;i++)
{
scanf("%d",&opt);
if (opt==1)
{
scanf("%d%d",&u,&v);
printf("%I64d\n",Segtree::query(u,v,1,n,1));
}
if (opt==2)
{
scanf("%d%d%d",&u,&v,&w);
Segtree::modify(u,v,1,n,1,w);
}
}
}
int main()
{
init();
work();
return 0;
}