注意:异或的操作时不可以直接下传的,否则会出问题
一个解决方式是按位建树,这时的懒标记是可以下传的,具体细节可以看代码
另外需要注意的是区间求和的时候要按位乘以2
这题在输出的时候要开long long,全不能开,会炸空间
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#include <bits/stdc++.h>
#define inf 0x7fffffff
#define ll long long
//#define int long long
//#define double long double
#define re int
#define void inline void
#define eps 1e-8
//#define mod 1e9+7
#define ls(p) p<<1
#define rs(p) p<<1|1
#define pi acos(-1.0)
#define pb push_back
#define P pair < int , int >
#define mk make_pair
using namespace std;
const int mod=998244353;
const int M=1e9+1;
const int N=4e5+5;
struct node
{
int l,r,sum,add;
}e[N][22];
int n,m;
void pushup(int p,int id)
{
e[p][id].sum=e[ls(p)][id].sum+e[rs(p)][id].sum;
}
void spread(int p,int id)
{
if(e[p][id].add)
{
e[ls(p)][id].sum=(e[ls(p)][id].r-e[ls(p)][id].l+1)-e[ls(p)][id].sum;
e[rs(p)][id].sum=(e[rs(p)][id].r-e[rs(p)][id].l+1)-e[rs(p)][id].sum;
e[ls(p)][id].add^=1;
e[rs(p)][id].add^=1;
e[p][id].add=0;
}
}
void bulid(int p,int id,int l,int r)
{
e[p][id].l=l,e[p][id].r=r;
e[p][id].add=e[p][id].sum=0;
if(l==r) return;
int mid=(l+r)>>1;
bulid(ls(p),id,l,mid);bulid(rs(p),id,mid+1,r);
pushup(p,id);
}
void insert(int p,int id,int pos)
{
if(e[p][id].l==e[p][id].r)
{
e[p][id].sum=1;
return;
}
int mid=(e[p][id].l+e[p][id].r)>>1;
if(pos<=mid) insert(ls(p),id,pos);
else insert(rs(p),id,pos);
pushup(p,id);
}
void change(int p,int id,int l,int r)
{
if(l<=e[p][id].l&&e[p][id].r<=r)
{
e[p][id].sum=(e[p][id].r-e[p][id].l+1)-e[p][id].sum;
e[p][id].add^=1;
return;
}
spread(p,id);
int mid=(e[p][id].l+e[p][id].r)>>1;
if(l<=mid) change(ls(p),id,l,r);
if(mid<r) change(rs(p),id,l,r);
pushup(p,id);
}
int ask(int p,int id,int l,int r)
{
if(l<=e[p][id].l&&e[p][id].r<=r) return e[p][id].sum;
spread(p,id);
int mid=(e[p][id].l+e[p][id].r)>>1;
int ans=0;
if(l<=mid) ans+=ask(ls(p),id,l,r);
if(mid<r) ans+=ask(rs(p),id,l,r);
return ans;
}
void solve()
{
cin>>n;
for(re i=0;i<21;i++) bulid(1,i,1,n);
for(re i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
for(re j=0;j<21&&x;j++,x>>=1) if(x&1) insert(1,j,i);
}
cin>>m;
while(m--)
{
int op,x,y,z;
ll ans=0;
scanf("%d%d%d",&op,&x,&y);
if(op==1)
{
ll cnt=1;
for(re j=0;j<21;j++,cnt*=2) ans+=cnt*ask(1,j,x,y);
printf("%lld\n",ans);
}
else
{
scanf("%d",&z);
for(re j=0;j<21&&z;j++,z>>=1) if(z&1) change(1,j,x,y);
}
}
}
signed main()
{
int T=1;
// cin>>T;
for(int index=1;index<=T;index++)
{
// printf("Case #%lld: ",index);
solve();
// puts("");
}
return 0;
}
/*
*/