题意:定义对集合的交、并、差、异或,求空集经过一系列操作后的结果。
题解:将原点集每一个点乘以2,形成一个新的点集,其中偶数点都对应着原来的点,奇数点对应着不包括它左右两个点的开区间,即2k+1==>(k,k+1),于是区间上所有点都能用整点表示,线段树可求解,对于每一个操作区间,无论开闭,都对应这线段树上的一段线段。
1、并运算[a,b],就是将[a,b]赋值为1.(a,b均为对应之后的点)
2、交运算[a,b],将除了[a,b]区间以外的线段清0.
3、S-[a,b],将[a,b]区间清0.
4、[a,b]-S,将[a,b]区间以外线段清0,并且将[a,b]线段所代表区域取反.
5、异或运算,上面两者去并,就是将[a,b]区域取反.
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cctype> 5 using namespace std; 6 const int maxn=66000*2; 7 const int N=maxn*4; 8 struct Line 9 { 10 int left,right; 11 int tag; 12 bool rev; 13 } line[N]; 14 void build(int now,int left,int right) 15 { 16 line[now].left=left; 17 line[now].right=right; 18 line[now].tag=0; 19 line[now].rev=false; 20 if(left==right) 21 return; 22 int mid=(left+right)>>1; 23 build(now*2,left,mid); 24 build(now*2+1,mid+1,right); 25 } 26 void pushdown(int now) 27 { 28 if(line[now].left==line[now].right) 29 { 30 if(line[now].rev) 31 { 32 line[now].tag^=1; 33 line[now].rev=false; 34 } 35 return; 36 } 37 if(line[now].tag!=-1) 38 { 39 if(line[now].rev) 40 line[now].tag^=1; 41 line[now*2].tag=line[now*2+1].tag=line[now].tag; 42 line[now].tag=-1; 43 line[now].rev=line[now*2].rev=line[now*2+1].rev=false; 44 } 45 if(line[now].rev) 46 { 47 line[now].rev=false; 48 if(line[now*2].tag==-1) 49 line[now*2].rev^=true; 50 else 51 line[now*2].tag^=1; 52 if(line[now*2+1].tag==-1) 53 line[now*2+1].rev^=true; 54 else 55 line[now*2+1].tag^=1; 56 } 57 } 58 void solve(int now,int left,int right,int op) 59 { 60 if(left>right) 61 return; 62 int ll=line[now].left,rr=line[now].right; 63 if(ll==left&&rr==right) 64 { 65 if(op<2) 66 { 67 line[now].rev=false; 68 line[now].tag=op; 69 } 70 else if(line[now].tag!=-1) 71 { 72 line[now].tag^=1; 73 } 74 else 75 { 76 line[now].rev^=1; 77 } 78 return; 79 } 80 int mid=(ll+rr)>>1; 81 pushdown(now); 82 if(mid<left) 83 { 84 solve(now*2+1,left,right,op); 85 } 86 else if(right<=mid) 87 { 88 solve(now*2,left,right,op); 89 } 90 else 91 { 92 solve(now*2,left,mid,op); 93 solve(now*2+1,mid+1,right,op); 94 } 95 } 96 bool vis[N]; 97 void findinter(int now) 98 { 99 if(line[now].tag!=-1) 100 { 101 if(line[now].tag==1) 102 { 103 int ll=line[now].left,rr=line[now].right; 104 for(int i=ll; i<=rr; i++) 105 vis[i]=true; 106 } 107 return; 108 } 109 pushdown(now); 110 findinter(now*2); 111 findinter(now*2+1); 112 } 113 int main() 114 { 115 build(1,0,maxn); 116 char s[100]; 117 while(gets(s)) 118 { 119 int len=strlen(s),i,op,a=0,b=0; 120 for(i=3;i<len;i++) 121 { 122 if(!isdigit(s[i])) 123 break; 124 a=a*10+s[i]-'0'; 125 } 126 for(i++;i<len;i++) 127 { 128 if(!isdigit(s[i])) 129 break; 130 b=b*10+s[i]-'0'; 131 } 132 if(s[i]==']') 133 b=b*2; 134 else 135 b=b*2-1; 136 if(s[2]=='[') 137 a=a*2; 138 else 139 a=a*2+1; 140 switch(s[0]) 141 { 142 case 'U':solve(1,a,b,1);break; 143 case 'I':solve(1,0,a-1,0);solve(1,b+1,maxn,0);break; 144 case 'D':solve(1,a,b,0);break; 145 case 'C':solve(1,0,a-1,0);solve(1,b+1,maxn,0);solve(1,a,b,2);break; 146 case 'S':solve(1,a,b,2);break; 147 } 148 } 149 memset(vis,false,sizeof(vis)); 150 findinter(1); 151 bool first=true; 152 for(int i=0; i<=maxn; i++) 153 { 154 if(!vis[i]) 155 continue; 156 int a=i,b; 157 while(vis[i]&&i<=maxn) 158 i++; 159 b=--i; 160 if(first) 161 first=false; 162 else 163 printf(" "); 164 if(a&1) 165 printf("(%d,",a/2); 166 else 167 printf("[%d,",a/2); 168 if(b&1) 169 printf("%d)",(b+1)/2); 170 else 171 printf("%d]",b/2); 172 } 173 if(first) 174 printf("empty set"); 175 printf("\n"); 176 return 0; 177 }