[FOJ 2105][Vjudge 35179] Digits Count [线段树]

来源:互联网 发布:python twisted下载 编辑:程序博客网 时间:2024/05/22 23:34

给一列数,可以让第l到r个数同时与、或、异或上某个数,或者求第l到r个数的和

数据范围:总共10^6个数,10^5次操作,每个数的大小在[0,16)内

把每个数都按照二进制分成4位,建立4棵线段树,线段树上有置零(与操作),置一(或操作),取反(异或操作)三种操作,有求和查询

#include <cstring>#include <cstdio>struct Node {int l,r,sum,lazy;Node *ls,*rs;Node () {}Node (int ll,int rr) {l=ll;r=rr;sum=0;lazy=0;ls=rs=NULL;}void *operator new (size_t,void *p) {return p;}void getLazy(int x) {if (x==0) return;else if (lazy==0) lazy=x;else if (x==1) lazy=1;else if (x==2) lazy=2;else if (lazy==1) lazy=2;else if (lazy==2) lazy=1;else lazy=0;}void down() {if (ls!=NULL) ls->getLazy(lazy);if (rs!=NULL) rs->getLazy(lazy);if (lazy==1) sum=r-l+1;else if (lazy==2) sum=0;else if (lazy==3) sum=r-l+1-sum;lazy=0;}};struct SegTree {Node a[2100000];Node *root,*las,*tmp;void clear(int x[],int n) {las=a;for (int i=0;i<n;i++) {tmp=new(las++)Node(i,i);tmp->sum=x[i];}root=makeTree(0,n-1);}Node *makeTree(int l,int r) {if (l==r) return a+l;Node *ans=new(las++)Node(l,r);int t=(l+r)/2;ans->ls=makeTree(l,t);ans->rs=makeTree(t+1,r);ans->sum=ans->ls->sum+ans->rs->sum;return ans;}void set(Node *from,int l,int r,int opt) {if (from->l==l&&from->r==r) {from->getLazy(opt);return;}from->down();int t=(from->l+from->r)/2;if (t>=r) set(from->ls,l,r,opt);else if (t<l) set(from->rs,l,r,opt);else {set(from->ls,l,t,opt);set(from->rs,t+1,r,opt);}from->ls->down();from->rs->down();from->sum=from->ls->sum+from->rs->sum;}int get(Node *from,int l,int r) {from->down();if (from->l==l&&from->r==r) return from->sum;int t=(from->l+from->r)/2;if (t>=r) return get(from->ls,l,r);else if (t<l) return get(from->rs,l,r);else return get(from->ls,l,t)+get(from->rs,t+1,r);}};int n,m;SegTree a[4];int b[1000000];int c[1000000];int main() {int t,i,j,opn,l,r,ans;char s[10];scanf("%d",&t);while (t--) {scanf("%d%d",&n,&m);for (i=0;i<n;i++) scanf("%d",&b[i]);for (i=0;i<4;i++) {for (j=0;j<n;j++) c[j]=((b[j]&(1<<i))!=0);a[i].clear(c,n);}for (i=0;i<m;i++) {scanf("%s",s);if (s[0]=='A') {scanf("%d%d%d",&opn,&l,&r);for (j=0;j<4;j++) {if ((opn&(1<<j))==0) a[j].set(a[j].root,l,r,2);}} else if (s[0]=='O') {scanf("%d%d%d",&opn,&l,&r);for (j=0;j<4;j++) {if ((opn&(1<<j))!=0) a[j].set(a[j].root,l,r,1);}} else if (s[0]=='X') {scanf("%d%d%d",&opn,&l,&r);for (j=0;j<4;j++) {if ((opn&(1<<j))!=0) a[j].set(a[j].root,l,r,3);}} else {scanf("%d%d",&l,&r);ans=0;for (j=0;j<4;j++) {//printf("%d ",a[j].get(a[j].root,l,r));ans+=a[j].get(a[j].root,l,r)*(1<<j);}//printf("\n");printf("%d\n",ans);}}}return 0;}


0 0