zoukankan      html  css  js  c++  java
  • 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
    ", 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
  • 相关阅读:
    AES算法加解密Java工具类AESUtil
    并发与高并发(二十二)高并发の服务降级与服务熔断思路
    并发与高并发(二十一) 高并发の应用限流思路
    并发与高并发(二十)高并发の应用拆分思路
    da5_模块
    day5_集合
    day5_递归调用
    day5_判断价格输入是否是正整数或正小数
    day5_函数_判断小数
    day5_函数_文件读写_用一个函数来满足文件的读或者写_应用默认参数
  • 原文地址:https://www.cnblogs.com/idy002/p/4297220.html
Copyright © 2011-2022 走看看