BZOJ3226 SDOI2008 校门外的区间 线段树
题意:给定一个空的数集,要求维护:1、区间求并 2、区间求交 3、区间求差 4、区间异或。每次操作后原区间变为操作后的区间,每个操作的区间可开可闭,求所有操作后的区间
题解:把每个点拆成开和闭两个,线段树维护就好。最后统计答案的时候暴力枚举每个位置即可
#include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> using namespace std; #define Lim (1<<17) typedef struct Node{ int l,r; bool Rev,v,Same; Node *lchild,*rchild; Node(){} Node(int _l,int _r):l(_l),r(_r),v(0),Rev(0),Same(1),lchild(0),rchild(0){} } *Tree; Tree Root; int M; char a,b,t; bool Flag; void Build(Tree &x,int l,int r){ x=new Node(l,r); if(l==r) return; int m=(l+r)>>1; Build(x->lchild,l,m),Build(x->rchild,m+1,r); } void Pushdown(Tree &x){ if(x->l==x->r) return; if(x->Same){ x->Same=0,x->lchild->Same=x->rchild->Same=1; x->lchild->v=x->rchild->v=x->v,x->lchild->Rev=x->rchild->Rev=0; } if(x->Rev){ x->Rev=0; x->lchild->Rev^=1,x->rchild->Rev^=1; } } void Update(Tree &x,int l,int r,bool v){ if(l<=x->l && x->r<=r){ x->Rev=0,x->Same=1,x->v=v; return; } Pushdown(x); int m=(x->l+x->r)>>1; if(l<=m) Update(x->lchild,l,r,v); if(r>m) Update(x->rchild,l,r,v); } void Reverse(Tree &x,int l,int r){ if(l<=x->l && x->r<=r){ x->Rev^=1; return; } Pushdown(x); int m=(x->l+x->r)>>1; if(l<=m) Reverse(x->lchild,l,r); if(r>m) Reverse(x->rchild,l,r); } bool Query(Tree &x,int p){ Pushdown(x); if(x->l==x->r) return x->v; int m=(x->l+x->r)>>1; if(p<=m) return Query(x->lchild,p); else return Query(x->rchild,p); } void Visit(Tree &x){ if(x->Same){ x->v^=x->Rev; return; } Pushdown(x); Visit(x->lchild),Visit(x->rchild); } int main(){ Build(Root,0,Lim); int l,r; while(scanf("%c %c%d,%d%c\n",&t,&a,&l,&r,&b)!=EOF){ l<<=1,r<<=1; if(a=='(') l++; if(b==')') r--; if(t=='U') Update(Root,l,r,1); if(t=='I'){ if(l) Update(Root,0,l-1,0); if(r<Lim) Update(Root,r+1,Lim,0); } if(t=='D') Update(Root,l,r,0); if(t=='C'){ if(l) Update(Root,0,l-1,0); if(r<Lim) Update(Root,r+1,Lim,0); Reverse(Root,l,r); } if(t=='S') Reverse(Root,l,r); } Visit(Root); for(int i=0,p=-1;i<=Lim;i++){ if(Query(Root,i) && p==-1) p=i; if(!Query(Root,i) && p!=-1){ cout << (p&1?"(":"[") << (p>>1) << "," << (i>>1) << (i&1?"]":")") << " "; Flag=1,p=-1; } } if(!Flag) cout << "empty set" << endl; return 0; }