这类题之前做过1道,是东北网络赛的A题,内题当时没做出来,听了学长的思路后,场下才AC的。。而这题是我完全独立完成,很有纪念意义的。。。嘿嘿。。
话说此题在CF竟然能暴力过关,真心严重B视。。。。应该把时限设在3S内才行。。。
题目是这样说的,做2种操作,一个是计算区间和,还有一个是区间所有数都异或某一个数。普通的成段更新肯定不行,我想到异或是对位计算,那就把1个数转化为二进制后,分位来处理,由于每一位异或1改变值,异或0不变。所以,对某个区间的某一位数异或0时,不改变区间和,若异或1,则总和=区间长度-区间和。。两次异或1为异或0。。代码搞出,后来WA的不明白,把空间改大点,AC了。。。。不容易呀,附代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#define lson i,l,m,rt<<1
#define rson i,m+1,r,rt<<1|1
#define N 100005
#define M 22
#define ss(a) scanf("%d",&a)
#define LL __int64
int sum[M][N*6],col[M][N*6],a[M][N],n;
LL c[M];
using namespace std;
void init(int j,int x)
{
int i=0;
while (x>0)
{
if (x&1) a[i][j]=1;
else a[i][j]=0;
x>>=1;
i++;
}
}
void pushup(int i,int rt)
{
sum[i][rt]=sum[i][rt<<1]+sum[i][rt<<1|1];
}
void pushdown(int i,int l,int r,int rt)
{
if (col[i][rt]%2!=0)
{
int m=(l+r)>>1;
sum[i][rt<<1]=(m-l+1)-sum[i][rt<<1];
sum[i][rt<<1|1]=(r-m)-sum[i][rt<<1|1];
col[i][rt<<1|1]+=col[i][rt];
col[i][rt<<1]+=col[i][rt];
col[i][rt]=0;
}
}
void build(int i,int l,int r,int rt)
{
if (l==r)
{
sum[i][rt]=a[i][l];
col[i][rt]=0;
return;
}
int m=(l+r)>>1;
build(lson);
build(rson);
pushup(i,rt);
}
void update(int L,int R,int i,int l,int r,int rt)
{
pushdown(i,l,r,rt);
if (L<=l&&r<=R)
{
sum[i][rt]=(r-l+1)-sum[i][rt];
col[i][rt]++;
return;
}
int m=(l+r)>>1;
if (L<=m) update(L,R,lson);
if (R>m) update(L,R,rson);
pushup(i,rt);
}
int query(int L,int R,int i,int l,int r,int rt)
{
pushdown(i,l,r,rt);
if (L<=l&&r<=R)
{
return sum[i][rt];
}
int m=(l+r)>>1,res=0;
if (L<=m) res+=query(L,R,lson);
if (R>m) res+=query(L,R,rson);
return res;
}
void bin(int l,int r,int x)
{
int i=0;
while (x>0)
{
if (x&1) update(l,r,i,1,n,1);
x>>=1;
i++;
}
}
LL inquery(int l,int r)
{
LL t,res=0;
int i;
for (i=0;i<M;i++)
{
t=query(l,r,i,1,n,1);
res+=t*c[i];
}
return res;
}
int main()
{
int i,z,x,l,r,m;
c[0]=1;
for (i=1;i<M;i++) c[i]=c[i-1]*2;
ss(n);
for (i=1;i<=n;i++)
{
ss(x);
init(i,x);
}
for (i=0;i<M;i++) build(i,1,n,1);
ss(m);
for (i=1;i<=m;i++)
{
ss(z);
if (z==1)
{
ss(l);ss(r);
LL res=inquery(l,r);
printf("%I64d\n",res);
}
else
{
ss(l);ss(r);ss(x);
bin(l,r,x);
}
}
return 0;
}