poj 3225 线段树+位运算
略复杂的一道题,首先要处理开闭区间问题,扩大两倍即可,注意输入最后要\n,初始化不能随便memset
采用线段树,对线段区间进行0,1标记表示该区间是否包含在s内
U T S ← S ∪ T 即将[l,r]标记为1
I T S ← S ∩ T 即将-oo~l和r~+oo标记为0,因为是并集,所以并集后的集合s一定在[l,r]内,则在l,r内的集合被标记是什么状态就是什么状态(表示是否属于s),[l,r]外的集合不属于s所以标记为0
D T S ← S - T 即将[l,r]标记为0,则在[l,r]内被s包含的集合也会标记为0表示不再属于s
C T S ← T - S 即先将-oo~l,r~+oo标记为0,这部分不属于[l,r]则一定不属于s,然后将[l,r]的标记0/1互换,因为属于s的不再属于s,不属于s的将属于s
S T S ← S ⊕ T 即属于s的不变,[l,r]中不属于s的(区间)0标记为1,属于s的(区间)1标记为0,所以[l,r]的标记0/1互换
最后对区间l,r标记时标记将l*2,r*2标记,如果是闭区间则对l*2+1,或r*2-1进行标记,则输出的时候只需判断奇偶就能判断开闭区间
是否覆盖0,1是否转换0,1的0,1转换都可以用异或去转换
Sample Input
U [1,5]
D [3,3]
S [2,4]
C (1,5)
I (2,3]
Sample Output
(2,3)
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 #define lson l,m,rt<<1 8 #define rson m+1,r,rt<<1|1 9 using namespace std; 10 const int maxn=131072; 11 int tot=0; 12 int n,m,t; 13 int Xor[maxn<<2],cov[maxn<<2]; //异或标记,覆盖标记 14 int hash[maxn<<2]; 15 void XXor(int rt) 16 { 17 if(cov[rt]!=-1) cov[rt]^=1; //说明该区域有值存在 18 else Xor[rt]^=1; 19 } 20 void pushdown(int rt) 21 { 22 if(cov[rt]!=-1) 23 { 24 cov[rt<<1]=cov[rt<<1|1]=cov[rt]; 25 Xor[rt<<1]=Xor[rt<<1|1]=0; 26 cov[rt]=-1; 27 } 28 if(Xor[rt]) 29 { 30 XXor(rt<<1); 31 XXor(rt<<1|1); 32 Xor[rt]=0; 33 } 34 } 35 void update(char op,int L,int R,int l,int r,int rt) 36 { 37 if(l>=L&&r<=R) 38 { 39 40 if(op=='U') cov[rt]=1,Xor[rt]=0; 41 else if(op=='D') cov[rt]=Xor[rt]=0; 42 else if(op=='C'||op=='S') XXor(rt); 43 return; 44 } 45 pushdown(rt); 46 int m=(l+r)>>1; 47 if(L<=m) update(op,L,R,lson); 48 else if(op=='I'||op=='C') cov[rt<<1]=Xor[rt<<1]=0; 49 if(m<R) update(op,L,R,rson); 50 else if(op=='I'||op=='C') cov[rt<<1|1]=Xor[rt<<1|1]=0; 51 } 52 void query(int l,int r,int rt) 53 { 54 if(cov[rt]==1) 55 { 56 for(int i=l;i<=r;i++) hash[i]=1; 57 return; 58 } 59 else if(cov[rt]==0) return; 60 if(l==r) return; 61 pushdown(rt); 62 int m=(r+l)>>1; 63 query(lson); 64 query(rson); 65 } 66 int main() 67 { 68 int i,j,k; 69 //freopen("1.in","r",stdin); 70 char l,r,op; 71 int a,b; 72 while(scanf("%c %c%d,%d%c\n",&op,&l,&a,&b,&r)!=EOF) 73 { 74 a<<=1,b<<=1; //区间扩大一倍,解决开闭区间问题 75 //printf("%d %d\n",a,b); 76 if(l=='(') a++; 77 if(r==')') b--; 78 if(a>b) //说明a和b的值相等 79 { 80 if(op=='C'||op=='I') cov[1]=Xor[1]=0,printf(""); //整个区间为0 81 } 82 else update(op,a,b,0,maxn,1); 83 } 84 k=0; 85 query(0,maxn,1); //此时区间内的有效区域值为1 86 int s=-1,e; //判断左右区间位置 87 88 for(i=0;i<=maxn;i++) 89 { 90 if(hash[i]) //该区域被覆盖 91 { 92 if(s==-1) s=i; 93 e=i; 94 } 95 else 96 { 97 if(s!=-1) //说明存在一个完整区间 98 { 99 if(k++) printf(" "); 100 printf("%c%d,%d%c",s&1?'(':'[',s>>1,(e+1)>>1,e&1?')':']'); //&运算用来判断奇偶,偶数的话二进制末位为0,and1得0,说明为闭区间 101 s=-1; 102 } 103 } 104 } 105 if(k==0) printf("empty set"); 106 puts(""); 107 return 0; 108 }