感觉还是上海人出题水平高?这套题写得心旷神怡的。。。总之很难就是啦
由于我实在不适应博客园这种排版和字体。。所以我的文章可能会特别难看大家见谅。。说不定回头开发一个支持全局LaTeX的博客也不错?2333
BZOJ1018 堵塞的交通:
题目大意:有一个2*n的矩阵,初始时没有边,每次可能会打通两个相邻的节点(相邻指曼哈顿距离为1)之间的无向道路或是拆毁两个相邻节点的道路,每次询问两个节点是否连通。
神奇的做法:使用动态树维护整个图的连通性!(这真的可写么?)
正确的做法:由于只有两排,使用一个线段树来维护连通性就可以了。。思路就是线段树的每个叶子节点维护四个节点的C字形的连通性,每个非叶子节点维护这一段的四个顶点的C字型(每个线段树节点其实是一个并查集) 虽然连接方式有很多种情况,但毕竟是有限的几种,手工特判一下就好了。。细节挺多的。特别要注意从两边联通这种情况。随便写一写就好了。
1 //date 20140624 2 #include <cstdio> 3 #include <cstring> 4 5 const int maxn = 105000; 6 7 inline int getint() 8 { 9 int ans(0); char w = getchar(); 10 while(w < '0' || '9' < w) w = getchar(); 11 while('0' <= w && w <= '9'){ans = ans * 10 + w - '0'; w = getchar();} 12 return ans; 13 } 14 15 template <typename T> inline void swap(T &a, T &b){T x = a; a = b; b = x;} 16 17 /* 18 0---------2 19 | | 20 | | 21 | | 22 1---------3 23 */ 24 int tmp[10]; 25 struct info 26 { 27 int num[4]; 28 info(){} 29 info(int a, int b, int c, int d){num[0] = a; num[1] = b; num[2] = c; num[3] = d;} 30 void std() 31 { 32 memset(tmp, 0, sizeof tmp); int count = 0; 33 for(int i = 0; i < 4; ++i) if(!tmp[num[i]]) tmp[num[i]] = ++count; 34 for(int i = 0; i < 4; ++i) num[i] = tmp[num[i]]; 35 } 36 }; 37 38 struct DSU 39 { 40 int p[7]; 41 void preset(){ for(int i = 1; i <= 6; ++i) p[i] = i;} 42 DSU(){preset();} 43 int getp(int x){return p[x] == x ? x : (p[x] = getp(p[x]));} 44 void merge(int x, int y){if((x = getp(x)) != (y = getp(y))) p[x] = y;} 45 }; 46 47 inline info operator+ (info A, info B) 48 { 49 DSU MEOW; 50 for(int i = 0; i < 3; ++i) for(int j = i + 1; j < 4; ++j) 51 if(A.num[i] == A.num[j]) MEOW.merge(i + 1, j + 1); 52 for(int i = 0; i < 3; ++i) for(int j = i + 1; j < 4; ++j) 53 if(B.num[i] == B.num[j]) MEOW.merge(i + 3, j + 3); 54 info ans(MEOW.getp(1), MEOW.getp(2), MEOW.getp(5), MEOW.getp(6)); ans.std(); 55 return ans; 56 } 57 58 int n; 59 info wius[8]; 60 int now[maxn]; 61 62 inline void preset() 63 { 64 wius[0] = info(1, 2, 3, 4); 65 wius[1] = info(1, 2, 1, 3); 66 wius[2] = info(1, 1, 2, 3); 67 wius[3] = info(1, 1, 1, 2); 68 wius[4] = info(1, 2, 3, 2); 69 wius[5] = info(1, 2, 1, 2); 70 wius[6] = info(1, 1, 2, 1); 71 wius[7] = info(1, 1, 1, 1); 72 } 73 74 75 struct zkw_sget 76 { 77 int base; info data[300000]; 78 void preset() 79 { 80 for(base = 1; base < n + 2; base <<= 1); 81 for(int i = 1; i < (base << 1); ++i) data[i] = wius[0]; 82 } 83 84 void change(int pos, int val) 85 { 86 data[pos + base] = wius[now[pos] = val]; 87 for(int i = (pos + base) >> 1; i; i >>= 1) data[i] = data[i << 1] + data[(i << 1) | 1]; 88 } 89 90 info mini_query(int l, int r) 91 { 92 info ansl(wius[5]), ansr(wius[5]); 93 for(l = l + base - 1, r = r + base + 1; l < r - 1; l >>= 1, r >>= 1) 94 { 95 if(!(l & 1)) ansl = ansl + data[l ^ 1]; 96 if( (r & 1)) ansr = data[r ^ 1] + ansr; 97 } 98 return ansl + ansr; 99 } 100 101 info query(int l, int r) 102 { 103 info ansl, ansm, ansr; 104 ansl = mini_query(1, l - 1); 105 ansm = mini_query(l, r - 1); 106 ansr = mini_query(r, n); 107 if(ansl.num[2] == ansl.num[3]) ansm = wius[7] + ansm; 108 if(ansr.num[0] == ansr.num[1]) ansm = ansm + wius[7]; 109 return ansm; 110 } 111 }MEOW; 112 113 char order[10]; 114 115 int main() 116 { 117 n = getint(); preset(); 118 MEOW.preset(); 119 while(true) 120 { 121 scanf("%s", order); 122 int x1, y1, x2, y2; 123 switch(order[0]) 124 { 125 case 'E': return 0; break; 126 case 'O': case 'C': 127 x1 = getint(); y1 = getint(); x2 = getint(); y2 = getint(); 128 if(y1 > y2){swap(x1, x2); swap(y1, y2);} 129 if(y1 == y2) 130 { 131 MEOW.change(y1, now[y1] ^ 2); 132 }else { 133 if(x1 == 1) MEOW.change(y1, now[y1] ^ 1); 134 else MEOW.change(y1, now[y1] ^ 4); 135 } 136 break; 137 138 case 'A': 139 x1 = getint(); y1 = getint(); x2 = getint(); y2 = getint(); 140 if(y1 > y2){swap(x1, x2); swap(y1, y2);} 141 info tmp = MEOW.query(y1, y2); 142 printf(tmp.num[x1 - 1] == tmp.num[x2 + 1] ? "Y\n" : "N\n"); 143 break; 144 } 145 } 146 return 0; 147 }