尽管下面那几行代码特别长,但是,您只需要看第85-97行,第100-102行,第123-128行即可。
#include <bits/stdc++.h>
#define int unsigned long long
using namespace std;
int n,q,x,pos,opt,le,ri,k;
int a[100005][31],tree[31][400005],tag[31][400005],p[31],tmp[31];
inline void pushup(int t,int rt)
{
tree[t][rt]=tree[t][2*rt]+tree[t][2*rt+1];
}
inline void build_tree(int t,int l,int r,int rt)
{
if (l==r)
{
tree[t][rt]=a[l][t];
return;
}
int mid=(l+r)>>1;
build_tree(t,l,mid,2*rt);
build_tree(t,mid+1,r,2*rt+1);
pushup(t,rt);
}
inline void f(int t,int l,int r,int rt)
{
tree[t][rt]=(r-l+1)-tree[t][rt];
tag[t][rt]=(tag[t][rt]+1)%2;
}
inline void pushdown(int t,int l,int r,int rt)
{
if (tag[t][rt])
{
int mid=(l+r)>>1;
f(t,l,mid,2*rt);
f(t,mid+1,r,2*rt+1);
}
tag[t][rt]=0;
}
inline void change(int t,int nl,int nr,int l,int r,int rt)
{
if (nl<=l&&r<=nr)
{
f(t,l,r,rt);
return;
}
pushdown(t,l,r,rt);
int mid=(l+r)>>1;
if (nl<=mid) change(t,nl,nr,l,mid,2*rt);
if (nr>mid) change(t,nl,nr,mid+1,r,2*rt+1);
pushup(t,rt);
}
inline int query(int t,int nl,int nr,int l,int r,int rt)
{
pushdown(t,l,r,rt);
int mid=(l+r)>>1,tot=0;
if (nl<=l&&r<=nr) return tree[t][rt];
if (nl<=mid) tot=query(t,nl,nr,l,mid,2*rt);
if (nr>mid) tot+=query(t,nl,nr,mid+1,r,2*rt+1);
return tot;
}
inline void init()
{
p[0]=1;
for (int i=1;i<=25;i++) p[i]=(p[i-1]*2);
}
inline int segment_query(int le,int ri)
{
int ans=0;
for (int i=1;i<=25;i++) ans+=p[25-i]*query(i,le,ri,1,n,1);
return ans;
}
inline void segment_change(int le,int ri,int k)
{
pos=25;
while (k)
{
tmp[pos]=k%2;
pos--;
k/=2;
}
for (int i=1;i<=25;i++)
{
if (tmp[i]) change(i,le,ri,1,n,1);
}
}
inline void clear()
{
for (int i=1;i<=30;i++) tmp[i]=0;
}
signed main()
{
cin>>n;
init();
for (int i=1;i<=n;i++)
{
cin>>x;
pos=25;
while (x)
{
a[i][pos]=x%2;
x/=2,pos--;
}
}
for (int i=1;i<=25;i++) build_tree(i,1,n,1);
cin>>q;
while (q--)
{
clear();
cin>>opt>>le>>ri;
if (opt==1) cout<<segment_query(le,ri)<<endl;
else cin>>k,segment_change(le,ri,k);
}
return 0;
}