二维线段树,卡了一下午,求和时,sum会溢出,所以类型用__int64
#include<cstdio> using namespace std; const int MAXN = 811111; struct tree{ int cnt[MAXN], lazy[MAXN]; inline void rev(int id, int l, int r) { cnt[id] = r-l+1-cnt[id]; lazy[id]^=1; } void update(int id, int l, int r, int st, int en) { if(l==st&&r==en) { rev(id,l,r); return ; } int mid = (st+en)>>1; if(lazy[id]) { lazy[id]=0; rev(id<<1,st,mid); rev(id<<1|1, mid+1,en); } if(r<=mid) update(id<<1,l,r,st,mid); else if(l>mid) update(id<<1|1,l,r,mid+1,en); else { update(id<<1,l,mid,st,mid); update(id<<1|1,mid+1,r,mid+1,en); } cnt[id] = cnt[id<<1]+cnt[id<<1|1]; } int query(int id, int l, int r, int st, int en) { if(l==st&&r==en) return cnt[id]; int mid = (st+en)>>1; if(lazy[id]) { lazy[id]=0; rev(id<<1,st,mid); rev(id<<1|1, mid+1,en); } int ans =0 ; if(r<=mid) ans = query(id<<1,l,r,st,mid); else if(l>mid) ans = query(id<<1|1,l,r,mid+1,en); else { ans = query(id<<1,l,mid,st,mid)+query(id<<1|1,mid+1,r,mid+1,en); } cnt[id]=cnt[id<<1]+cnt[id<<1|1]; return ans; } }T[20]; int main() { int n;scanf("%d",&n); for(int i=1; i<=n;i++) { int x;scanf("%d",&x); for(int j=0; j<20; ++j) if(x&(1<<j))T[j].update(1,i,i,1,n); } int m;scanf("%d",&m); while(m--) { int comm;scanf("%d",&comm); if(comm==1) { int l, r;scanf("%d%d",&l,&r); __int64 sum = (__int64) 0; for(int i=0; i<20; i++) sum+=(__int64)(1<<i)*T[i].query(1,l,r,1,n); printf("%I64d\n",sum); } else { int l,r,x;scanf("%d%d%d",&l,&r,&x); for(int i=0; i<20; ++i) if(x&(1<<i)) T[i].update(1,l,r,1,n); } } return 0; }