码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj 1018 线段树维护连通性

时间:2015-02-21 23:27:53      阅读:389      评论:0      收藏:0      [点我收藏+]

标签:

 

本题将一道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 }
View Code

 

bzoj 1018 线段树维护连通性

标签:

原文地址:http://www.cnblogs.com/idy002/p/4297220.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!