bzoj 1018 线段树维护连通性
本题将一道LCT的题特殊化(支持加边和删边,询问图的连通性),将图变成了2×m的网格图,然后就神奇地可以用线段树来维护。
对于每个区间[l,r],维护其四个角落之间的连通性(仅仅通过[l,r]这段的边构建起的连通性)。
查询[l,r]时,先计算出[1,l-1],[l,r],[r+1,c]这三个线段的连通性,然后将[l,r]的四个角变成并查集的4个点,先用[l,r]中的6种关系更新,在看是否可以从左上角的点通过左边区间绕道左下角,以及从右上角通过右边区间绕道右下角,该并的并起来后直接看查询的点是否在一个集合即可。
1 /************************************************************** 2 Problem: 1018 3 User: idy002 4 Language: C++ 5 Result: Accepted 6 Time:1472 ms 7 Memory:2840 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <iostream> 12 #define maxn 100010 13 #define AB 1 14 #define AC 2 15 #define AD 4 16 #define BC 8 17 #define BD 16 18 #define CD 32 19 using namespace std; 20 21 // a b 22 // c d 23 24 typedef unsigned Stat; 25 26 Stat stat[maxn]; 27 int son[maxn][2], ntot, root; 28 29 int c; 30 bool er[3][maxn], ed[maxn]; 31 32 Stat merge( Stat l, Stat r, int mid ) { 33 Stat ab = ((l&AB)&&(r&AB)&&er[1][mid]) || ((l&AD)&&(r&BC)&&er[2][mid]) ? AB : 0; 34 Stat cd = ((l&CD)&&(r&CD)&&er[2][mid]) || ((l&BC)&&(r&AD)&&er[1][mid]) ? CD : 0; 35 Stat ad = ((l&AB)&&(r&AD)&&er[1][mid]) || ((l&AD)&&(r&CD)&&er[2][mid]) ? AD : 0; 36 Stat bc = ((l&CD)&&(r&BC)&&er[2][mid]) || ((l&BC)&&(r&AB)&&er[1][mid]) ? BC : 0; 37 Stat ac = (l&AC) || ((l&AB)&&(l&CD)&&(er[1][mid])&&(er[2][mid])&&(r&AC)) ? AC : 0; 38 Stat bd = (r&BD) || ((r&AB)&&(r&CD)&&(er[1][mid])&&(er[2][mid])&&(l&BD)) ? BD : 0; 39 return ab | ac | ad | bc | bd | cd; 40 } 41 void update( int nd, int lf, int rg ) { 42 stat[nd] = merge( stat[son[nd][0]], stat[son[nd][1]], (lf+rg)>>1 ); 43 } 44 int build( int lf, int rg ) { 45 if( lf>rg ) return 0; 46 int nd = ++ntot; 47 if( lf==rg ) { 48 stat[nd] = AB | CD; 49 return nd; 50 } 51 int mid = (lf+rg)>>1; 52 son[nd][0] = build( lf, mid ); 53 son[nd][1] = build( mid+1, rg ); 54 update( nd, lf, rg ); 55 return nd; 56 } 57 void modify( int x, int nd, int lf, int rg ) { 58 if( lf==rg ) { 59 stat[nd] = AB | CD; 60 if( ed[lf] ) 61 stat[nd] |= AC | BD | AD | BC; 62 return; 63 } 64 int mid = (lf+rg)>>1; 65 if( x<=mid ) modify(x,son[nd][0],lf,mid); 66 else modify(x,son[nd][1],mid+1,rg); 67 update(nd,lf,rg); 68 } 69 Stat query( int L, int R, int nd, int lf, int rg ) { 70 if( L<=lf&&rg<=R ) return stat[nd]; 71 int mid = (lf+rg)>>1; 72 if( R<=mid ) return query( L, R, son[nd][0], lf, mid ); 73 if( L>mid ) return query( L, R, son[nd][1], mid+1, rg ); 74 Stat lstat = query( L, R, son[nd][0], lf, mid ); 75 Stat rstat = query( L, R, son[nd][1], mid+1, rg ); 76 return merge(lstat,rstat,mid); 77 } 78 79 int fa[5]; 80 void init() { 81 for( int i=1; i<=4; i++ ) fa[i]=i; 82 } 83 int find( int i ) { 84 return fa[i]==i ? i : fa[i]=find(fa[i]); 85 } 86 void unon( int a, int b ) { 87 a = find(a); 88 b = find(b); 89 fa[a] = b; 90 } 91 int main() { 92 scanf( "%d", &c ); 93 root = build( 1, c ); 94 while(1) { 95 char ch[10]; 96 97 scanf( "%s", ch ); 98 if( ch[0]=='E' ) return 0; 99 int ax, ay, bx, by; 100 scanf( "%d%d%d%d", &ax, &ay, &bx, &by ); 101 102 if( ch[0]=='A' ) { 103 if( ay>by ) { 104 swap( ax, bx ); 105 swap( ay, by ); 106 } 107 Stat sl=0, sc=0, sr=0; 108 if( ay>1 ) sl = query(1,ay-1,root,1,c); 109 sc = query(ay,by,root,1,c); 110 if( by<c ) sr = query(by+1,c,root,1,c); 111 112 init(); 113 if( sc&AB ) unon( 1, 2 ); 114 if( sc&AC ) unon( 1, 3 ); 115 if( sc&AD ) unon( 1, 4 ); 116 if( sc&BC ) unon( 2, 3 ); 117 if( sc&BD ) unon( 2, 4 ); 118 if( sc&CD ) unon( 3, 4 ); 119 if( (sl&BD) && er[1][ay-1] && er[2][ay-1] ) unon( 1, 3 ); 120 if( (sr&AC) && er[1][by] && er[2][by] ) unon( 2, 4 ); 121 122 bool ok = false; 123 if( ax==1 && bx==1 ) { 124 ok = find( 1 ) == find( 2 ); 125 } else if( ax==1 && bx==2 ) { 126 ok = find( 1 ) == find( 4 ); 127 } else if( ax==2 && bx==1 ) { 128 ok = find( 3 ) == find( 2 ); 129 } else if( ax==2 && bx==2 ) { 130 ok = find( 3 ) == find( 4 ); 131 } 132 133 printf( "%s\n", ok ? "Y" : "N" ); 134 } else { 135 bool *p; 136 if( ax==bx ) { 137 p = &er[ax][min(ay,by)]; 138 } else { 139 p = &ed[ay]; 140 } 141 *p = ch[0]=='O'; 142 modify( ay, root, 1, c ); 143 if( ay!=by ) 144 modify( by, root, 1, c ); 145 } 146 } 147 }