BZOJ 1018 堵塞的交通 線段樹維護連通性
阿新 • • 發佈:2018-09-17
作用 rect build return enter shu ret urn swap
Time Limit: 3 Sec $ \quad $ Memory Limit: 162 MB
初來咋到的你決心毛遂自薦到交通部某份差事,部長聽說你來自一個科技高度發達的世界,
喜出望外地要求你編寫一個查詢應答系統,以挽救已經病入膏肓的小人國交通系統。
小人國的交通部將提供一些交通信息給你,你的任務是根據當前的交通情況回答查詢的問題。交通信息可以分為以下幾種格式:
$ \Rightarrow $ 戳我進BZOJ原題
[SHOI2008]堵塞的交通traffic
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 堵塞的交通 線段樹維護連通性