很早以前做过这题,早就没印象了,估计当时也是照着某大神的代码抄过的,现在是连题意都看了好长时间。
刚开始的S集合是空集,给你一些操作和一个T集合,把操作的结果再赋给S集合。
解法:因为会有开区间和闭区间,对于一个值我拆成了两个点 比如 1,2,3, 表示的区间为[1,2] 把两个端点值分别设为2个点,把端点之间的区间也设为一个点,那么 区间就可以表示为(1,2) = 1,[1,2) = 1,2 (1,2] = 2,3 ,把这些点建成树,然后进行区间的操作,也就转换成了对点的操作。
并操作,就是直接把a-b变为1.
S-T 操作。 直接把T的区间段变为0.
T-S 操作, 这个需要特别说明一下,因为这个操作的结果是把T之外的区间清零,把T这段区间的值变为相反的,这个不能用延迟覆盖来操作,需要加一个延迟标记,表示这段区间我需要逆置。
异或操作,异或操作的结果就是 T之外的区间不变化,T这段区间逆置,跟上面类似。
如果此段已有逆置的延迟标记,再加一个的话相当于抵消。
忘记判空集 ,WA一次。
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 140000 12 #define M 132000 13 #define LL long long 14 #define INF 0xfffffff 15 const double eps = 1e-8; 16 const double pi = acos(-1.0); 17 const double inf = ~0u>>2; 18 int s[N<<2],a[N],xlz[N<<2],lz[N<<2]; 19 struct node 20 { 21 int l,r,f; 22 }p[N]; 23 void down(int w,int m) 24 { 25 if(lz[w]!=-1) 26 { 27 s[w<<1] = s[w<<1|1] = lz[w<<1] = lz[w<<1|1] = lz[w]; 28 xlz[w<<1] = xlz[w<<1|1] = 0; 29 lz[w] = -1; 30 } 31 if(xlz[w]) 32 { 33 xlz[w<<1] ^= 1; 34 xlz[w<<1|1] ^= 1; 35 xlz[w] = 0; 36 } 37 } 38 void build(int l,int r,int w) 39 { 40 lz[w] = -1; 41 xlz[w] = 0; 42 s[w] = 0; 43 if(l==r) 44 { 45 return ; 46 } 47 int m = (l+r)>>1; 48 build(l,m,w<<1); 49 build(m+1,r,w<<1|1); 50 } 51 void update(int a,int b,int p,int d,int l,int r,int w) 52 { 53 if(a<=l&&b>=r) 54 { 55 //cout<<l<<" "<<r<<" "<<w<<endl; 56 if(p==1) 57 { 58 s[w] = d; 59 lz[w] = d; 60 xlz[w] = 0; 61 } 62 else 63 { 64 xlz[w] ^= 1 ; 65 } 66 return; 67 } 68 down(w,r-l+1); 69 int m = (l+r)>>1; 70 if(a<=m) update(a,b,p,d,l,m,w<<1); 71 if(b>m) update(a,b,p,d,m+1,r,w<<1|1); 72 } 73 int query(int p,int l,int r,int w) 74 { 75 if(l==r) 76 { 77 if(xlz[w]) 78 { 79 s[w]^=1; 80 xlz[w] ^= 1; 81 } 82 return s[w]; 83 } 84 down(w,r-l+1); 85 int m = (l+r)>>1; 86 if(p<=m) return query(p,l,m,w<<1); 87 else return query(p,m+1,r,w<<1|1); 88 } 89 int main() 90 { 91 int x,y,i; 92 char sr[5],c1,c2; 93 build(1,M,1); 94 while(scanf("%s",sr)!=EOF) 95 { 96 getchar(); 97 scanf("%c%d,%d%c",&c1,&x,&y,&c2); 98 x = (c1==‘[‘?2*x+1:2*x+2); 99 y = (c2==‘]‘?2*y+1:2*y); 100 if(sr[0]==‘U‘) 101 { 102 update(x,y,1,1,1,M,1); 103 } 104 else if(sr[0]==‘I‘) 105 { 106 if(x>1) 107 update(1,x-1,1,0,1,M,1); 108 update(y+1,M,1,0,1,M,1); 109 } 110 else if(sr[0]==‘D‘) 111 { 112 update(x,y,1,0,1,M,1); 113 } 114 else if(sr[0]==‘C‘) 115 { 116 if(x>1) 117 update(1,x-1,1,0,1,M,1); 118 update(y+1,M,1,0,1,M,1); 119 update(x,y,2,0,1,M,1); 120 } 121 else 122 { 123 update(x,y,2,0,1,M,1); 124 } 125 } 126 int g = 0; 127 for(i = 1; i <= M ;i++) 128 a[i] = query(i,1,M,1); 129 for(i = 1 ; i <= M ; i++) 130 { 131 if(a[i]&&a[i]!=a[i-1]) 132 { 133 g++; 134 p[g].l = (i-1)/2; 135 p[g].f = (i%2?1:0); 136 } 137 else if(a[i]!=a[i-1]) 138 { 139 p[g].r = (i-1)/2; 140 p[g].f+=((i-1)%2?2:0); 141 } 142 } 143 for(i = 1 ; i <= g ;i++) 144 { 145 if(p[i].f==0) 146 printf("(%d,%d)",p[i].l,p[i].r); 147 else if(p[i].f==1) 148 printf("[%d,%d)",p[i].l,p[i].r); 149 else if(p[i].f==2) 150 printf("(%d,%d]",p[i].l,p[i].r); 151 else 152 printf("[%d,%d]",p[i].l,p[i].r); 153 if(i!=g) printf(" "); 154 } 155 if(g==0) puts("empty set"); 156 else 157 puts(""); 158 return 0; 159 }
Help with Intervals(集合的交并补,线段树),布布扣,bubuko.com
Help with Intervals(集合的交并补,线段树)
原文地址:http://www.cnblogs.com/shangyu/p/3766388.html