1. 程式人生 > >BZOJ 1018 堵塞的交通 線段樹維護連通性

BZOJ 1018 堵塞的交通 線段樹維護連通性

作用 rect build return enter shu ret urn swap

$ \Rightarrow $ 戳我進BZOJ原題

[SHOI2008]堵塞的交通traffic

Time Limit: 3 Sec $ \quad $ Memory Limit: 162 MB

 

Description

有一天,由於某種穿越現象作用,你來到了傳說中的小人國。
小人國的布局非常奇特,整個國家的交通系統可以被看成是一個$ 2 $ 行 $ C $ 列的矩形網格,
網格上的每個點代表一個城市,相鄰的城市之間有一條道路,所以總共有 $ 2 \times C $個城市和 $ 3 \times C?2 $ 條道路。

小人國的交通狀況非常槽糕。有的時候由於交通堵塞,兩座城市之間的道路會變得不連通,直到擁堵解決,道路才會恢復暢通。

初來咋到的你決心毛遂自薦到交通部某份差事,部長聽說你來自一個科技高度發達的世界,
喜出望外地要求你編寫一個查詢應答系統,以挽救已經病入膏肓的小人國交通系統。
小人國的交通部將提供一些交通信息給你,你的任務是根據當前的交通情況回答查詢的問題。交通信息可以分為以下幾種格式:

  • Close r1 c1 r2 c2:相鄰的兩座城市 $ (r_1,c_1) $ 和 $ (r_2, c_2 ) $ 之間的道路被堵塞了;
  • Open r1 c1 r2 c2:相鄰的兩座城市 $ (r_1, c_1) $ 和 $ (r_2, c_2) $ 之間的道路被疏通了;
  • Ask r1 c1 r2 c2:詢問城市$ (r_1, c_1) $ 和 $ (r_2, c_2) $ 是否連通。如果存在一條路徑使得這兩條城市連通,則返回Y,否則返回N。

註:$ r_i $ 表示行數,$ c_i $ 表示列數,$ 1≤ri≤2,1≤ci≤C1 \leq r_i \leq 2, 1 \leq c_i \leq C $ 。
 

Input

第一行只有一個整數 $ C $ ,表示網格的列數。
接下來若幹行,每行為一條交通信息,以單獨的一行Exit作為結束。我們假設在一開始所有的道路都是堵塞的。
我們保證 $ C $ 小於等於 $ 100000 $ ,信息條數小於等於 $ 100000 $ 。
 

Output

對於每個查詢,輸出一個Y或N。
 

Sample Input

 2 
 Open 1 1 1 2
 Open 1 2 2 2
 Ask 1 1 2 2
 Ask 2 1 2 2
 Exit

Sample Output

 Y
 N

 

HINT

題解:JudgeOnline/upload/201604/sol(4).rar
 

代碼

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
#define N 200005
inline int read() {
    register char ch;
    while(!isdigit(ch=getchar()));
    register int x=ch^'0';
    while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    return x;
}
int n;
char opt[5];
struct tree{ bool e[3][3]; }t[N<<2];
int a[N<<2][2];
void build(int o,int l,int r){
    if(l==r){
        t[o].e[0][0]=t[o].e[1][1]=1;
        return;
    }
    int mid=l+r>>1;
    build(o<<1,l,mid); build(o<<1|1,mid+1,r);
}
void pushup(int o,int l,int r){
    if(l==r) return;
    int L=o<<1,R=o<<1|1,mid=l+r>>1;
    t[o].e[0][0] = (t[L].e[0][0] && t[R].e[0][0] && a[mid][0]) || (t[L].e[0][1] && t[R].e[1][0] && a[mid][1]);
    t[o].e[0][1] = (t[L].e[0][0] && t[R].e[0][1] && a[mid][0]) || (t[L].e[0][1] && t[R].e[1][1] && a[mid][1]);
    t[o].e[1][0] = (t[L].e[1][0] && t[R].e[0][0] && a[mid][0]) || (t[L].e[1][1] && t[R].e[1][0] && a[mid][1]);
    t[o].e[1][1] = (t[L].e[1][0] && t[R].e[0][1] && a[mid][0]) || (t[L].e[1][1] && t[R].e[1][1] && a[mid][1]);
    t[o].e[2][0] = t[L].e[2][0] || (t[o].e[0][1] && t[o].e[1][1]) || (t[o].e[0][0] && t[o].e[1][0]) || (t[o].e[0][0] && t[o].e[1][1] && t[R].e[2][1]) || (t[L].e[0][0] && t[L].e[1][1] && t[R].e[2][0] && a[mid][0] && a[mid][1]);
    t[o].e[2][1] = t[R].e[2][1] || (t[o].e[0][0] && t[o].e[0][1]) || (t[o].e[1][0] && t[o].e[1][1]) || (t[o].e[0][0] && t[o].e[1][1] && t[L].e[2][0]) || (t[R].e[0][0] && t[R].e[1][1] && t[L].e[2][1] && a[mid][0] && a[mid][1]);
}
void updata_row(int o,int l,int r,int x,int p){
    //p==1 : open   p==0 : close
    if(l==r){
        t[o].e[0][0]=t[o].e[1][1]=1;
        t[o].e[1][0]=t[o].e[0][1]=t[o].e[2][0]=t[o].e[2][1]=p;
        return;
    }
    int mid=l+r>>1;
    if(x>mid) updata_row(o<<1|1,mid+1,r,x,p);
    else updata_row(o<<1,l,mid,x,p);
    pushup(o,l,r);
}
void updata_column(int o,int l,int r,int x,int c,int p){
    //p==1 : open   p==0 : close
    if(l==r){
        a[x][c]=p;
        return;
    }
    int mid=l+r>>1;
    if(x>mid) updata_column(o<<1|1,mid+1,r,x,c,p);
    else updata_column(o<<1,l,mid,x,c,p);
    pushup(o,l,r);
}
void work(int c1,int r1,int c2,int r2,int p){
    //p==1 : open   p==0 : close
    if(c1==c2) updata_row(1,1,n,c1,p);
    else {
        if(c1>c2) swap(c1,c2);
        if( (!a[c1][r1] && p==1) || (a[c1][r1] && p==0) )
            updata_column(1,1,n,c1,r1,p);
    }
}
tree query_direct(int o,int l,int r,int L,int R){
    if(L==l&&r==R) return t[o];
    int mid=l+r>>1;
    if(L>mid) return query_direct(o<<1|1,mid+1,r,max(mid+1,L),R);
    else if(R<=mid) return query_direct(o<<1,l,mid,L,min(mid,R));
    else {
        tree res,tL,tR;
        tL=query_direct(o<<1,l,mid,L,min(mid,R));
        tR=query_direct(o<<1|1,mid+1,r,max(mid+1,L),R);
        res.e[0][0] = (tL.e[0][0] && tR.e[0][0] && a[mid][0]) || (tL.e[0][1] && tR.e[1][0] && a[mid][1]);
        res.e[0][1] = (tL.e[0][0] && tR.e[0][1] && a[mid][0]) || (tL.e[0][1] && tR.e[1][1] && a[mid][1]);
        res.e[1][0] = (tL.e[1][0] && tR.e[0][0] && a[mid][0]) || (tL.e[1][1] && tR.e[1][0] && a[mid][1]);
        res.e[1][1] = (tL.e[1][0] && tR.e[0][1] && a[mid][0]) || (tL.e[1][1] && tR.e[1][1] && a[mid][1]);
        res.e[2][0] = tL.e[2][0] || (res.e[0][1] && res.e[1][1]) || (res.e[0][0] && res.e[1][0]) || (res.e[0][0] && res.e[1][1] && tR.e[2][1]) || (tL.e[0][0] && tL.e[1][1] && tR.e[2][0] && a[mid][0] && a[mid][1]);
        res.e[2][1] = tR.e[2][1] || (res.e[0][0] && res.e[0][1]) || (res.e[1][0] && res.e[1][1]) || (res.e[0][0] && res.e[1][1] && tL.e[2][0]) || (tR.e[0][0] && tR.e[1][1] && tL.e[2][1] && a[mid][0] && a[mid][1]);
        return res;
    }
}
bool query(int c1,int r1,int c2,int r2){
    if(c1>c2){ 
        swap(c1,c2); 
        swap(r1,r2); 
    }
    tree tmp=query_direct(1,1,n,c1,c2);
    if(tmp.e[r1][r2]) return 1;
    tree L=query_direct(1,1,n,1,c1);
    tree R=query_direct(1,1,n,c2,n);
    if(L.e[2][1] && tmp.e[r1^1][r2]) return 1;
    if(R.e[2][0] && tmp.e[r1][r2^1]) return 1;
    if(L.e[2][1] && R.e[2][0] && tmp.e[r1^1][r2^1]) return 1;
    return 0;
}
int main(){
    n=read();
    build(1,1,n);
    while(1){
        scanf("%s",opt);
        if(opt[0]=='E') break;
        int r1,c1,r2,c2;
        r1=read()-1; c1=read(); r2=read()-1; c2=read();
        if(opt[0]=='O') work(c1,r1,c2,r2,1);
        if(opt[0]=='C') work(c1,r1,c2,r2,0);
        if(opt[0]=='A') query(c1,r1,c2,r2) ? puts("Y") : puts("N");
    }
    return 0;
}

BZOJ 1018 堵塞的交通 線段樹維護連通性