codeforces242E XOR on Segment
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。
本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!
题目链接:codeforces242E
正解:线段树
解题报告:
很快想出来之后写完就交,然后1A辣!
考虑这种和异或这类的位运算有关的题目,显然拆成位来考虑方便的多,需要资瓷区间修改、区间查询,那么就用线段树好了。
线段树上维护什么呢?
考虑把区间异或上$x$,如果$x$的第$i$位为$1$,相当于是把区间内所有的数的第$i$位从$1$变$0$,从$0$变$1$,显然我在线段树上维护区间内每一位的$1$、$0$出现次数就好了,修改的时候打个标记,把$0$、$1$的出现次数$swap$一下,查询的时候扫一遍算贡献。
//It is made by ljh2000 //有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。 #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> #include <ctime> #include <vector> #include <queue> #include <map> #include <set> #include <string> #include <complex> #include <bitset> using namespace std; typedef long long LL; typedef long double LB; typedef complex<double> C; const double pi = acos(-1); const int MAXN = 100011; int n,m,ql,qr,mo[45],CC,lin; LL ans; struct node{ int tag; int s[21][2]; }a[MAXN*3]; inline int getint(){ int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar(); if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w; } inline void update(int root){ int lc=root<<1,rc=root<<1|1; for(int i=20;i>=0;i--) for(int j=0;j<2;j++) a[root].s[i][j]=a[lc].s[i][j]+a[rc].s[i][j]; } inline void build(int root,int l,int r){ if(l==r) { lin=getint(); for(int i=20;i>=0;i--) a[root].s[i][(lin>>i)&1]++; return ; } int mid=(l+r)>>1,lc=root<<1,rc=root<<1|1; build(lc,l,mid); build(rc,mid+1,r); update(root); } inline void pushdown(int root,int l,int r){ if(a[root].tag==0) return ; if(l==r) { a[root].tag=0; return ; } lin=a[root].tag; a[root].tag=0; int lc=root<<1,rc=root<<1|1; a[lc].tag^=lin; a[rc].tag^=lin; for(int i=0;i<=20;i++) if((lin>>i)&1) { swap(a[lc].s[i][0],a[lc].s[i][1]); swap(a[rc].s[i][0],a[rc].s[i][1]); } } inline void query(int root,int l,int r){ pushdown(root,l,r); if(ql<=l && r<=qr) { for(int i=0;i<=20;i++) ans+=1LL*mo[i]*a[root].s[i][1]; return ; } int mid=(l+r)>>1,lc=root<<1,rc=root<<1|1; if(ql<=mid) query(lc,l,mid); if(qr>mid) query(rc,mid+1,r); } inline void modify(int root,int l,int r){ pushdown(root,l,r); if(ql<=l && r<=qr) { a[root].tag^=CC; for(int i=0;i<=20;i++) if((CC>>i)&1) swap(a[root].s[i][0],a[root].s[i][1]); return ; } int mid=(l+r)>>1,lc=root<<1,rc=root<<1|1; if(ql<=mid) modify(lc,l,mid); if(qr>mid) modify(rc,mid+1,r); update(root); } inline void work(){ n=getint(); build(1,1,n); for(int i=0;i<21;i++) mo[i]=(1<<i); m=getint(); int type; while(m--) { type=getint(); ql=getint(); qr=getint(); if(type==1) { ans=0; query(1,1,n); printf("%I64d\n",ans); } else { CC=getint(); modify(1,1,n); } } } int main() { work(); return 0; } //有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!