BZOJ1018 [SHOI2008]堵塞的交通traffic


本文版權歸ljh2000和博客園共有,歡迎轉載,但須保留此聲明,並給出原文鏈接,謝謝合作。

 

 

本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
轉載請注明出處,侵權必究,保留最終解釋權!

Description

  有一天,由於某種穿越現象作用,你來到了傳說中的小人國。小人國的布局非常奇特,整個國家的交通系統可
以被看成是一個2行C列的矩形網格,網格上的每個點代表一個城市,相鄰的城市之間有一條道路,所以總共有2C個
城市和3C-2條道路。 小人國的交通狀況非常槽糕。有的時候由於交通堵塞,兩座城市之間的道路會變得不連通,
直到擁堵解決,道路才會恢復暢通。初來咋到的你決心毛遂自薦到交通部某份差事,部長聽說你來自一個科技高度
發達的世界,喜出望外地要求你編寫一個查詢應答系統,以挽救已經病入膏肓的小人國交通系統。 小人國的交通
部將提供一些交通信息給你,你的任務是根據當前的交通情況回答查詢的問題。交通信息可以分為以下幾種格式:
Close r1 c1 r2 c2:相鄰的兩座城市(r1,c1)和(r2,c2)之間的道路被堵塞了;Open r1 c1 r2 c2:相鄰的兩座城
市(r1,c1)和(r2,c2)之間的道路被疏通了;Ask r1 c1 r2 c2:詢問城市(r1,c1)和(r2,c2)是否連通。如果存在一
條路徑使得這兩條城市連通,則返回Y,否則返回N;

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

 

 

正解:線段樹

解題報告:

  4月份的時候做過這道題,才發現線段樹可以這么玩...的的確確還有很多線段樹的神奇之處沒有被我發現...

  這道題的巧妙之處就在於它的線段是維護的是一個矩形內部的連通性。考慮對於一個矩形,我們用6個變量即可表示出兩兩的連通情況,不妨從1到6編號。線段樹的葉子結點維護的是最小的矩形,也就是長寬都為1的。而這個矩形的上一級就是相鄰兩個矩形的組合而成的2*1的矩形。可以發現中間有一列被兩邊矩形所共用,我們就可以根據分類討論,從兩個兒子結點推得父親結點的連通情況。

  那么我用兩個線段樹,一個表示實際的道路開通情況(這個其實可以不用線段樹,這里方便起見也一起用線段樹),另一個表示連通情況。那么修改的時候修改前者並且從底往上重新推出連通情況就可以了。

  至於詢問的話,就要費一點功夫了。我們先考慮在同一列的情況,那毫無疑問,查一下以這一列為右端的矩形和這一列為左端的矩形,直接判掉即可。

  如果不在同一列呢?

  我們考慮如果直接查詢這兩列之間的矩陣,然后根據兩個點處在哪一行來判斷的話會忽略一種情況:從左邊繞一大圈,或者從右邊繞一大圈然后連通。

  也就是說我並不知道可不可以繞道連通。解決辦法是查詢這兩列兩邊的矩陣,來更新中間矩陣的連通關系,再做判斷,這樣就可以保證正確性了。BZOJ似乎放了一份題解,雖然講的不詳細但是附了一幅圖,圖片還比較清楚地表現了上述情況。

  細節比較多,不寫拍很虛啊!這種題考場上不拍的話期望得分0分。

 

  1 //It is made by ljh2000
  2 #include <iostream>
  3 #include <cstdlib>
  4 #include <cstring>
  5 #include <cstdio>
  6 #include <cmath>
  7 #include <algorithm>
  8 #include <ctime>
  9 #include <vector>
 10 #include <queue>
 11 #include <map>
 12 #include <set>
 13 using namespace std;
 14 typedef long long LL;
 15 const int inf = (1<<30);
 16 const int MAXN = 100011;
 17 int n,ql,qr,pos,CC,type;
 18 char ch[12];
 19 bool ok;
 20 struct node{
 21     int l,r;
 22     int s,x,z,y,zxys,zsyx;//1、2、3、4、5、6
 23 }t[MAXN*4],a[MAXN*4],t1,t2,ans,ini;
 24 //t維護連通性,a維護實際開通的道路
 25 
 26 inline int getint()
 27 {
 28     int w=0,q=0; char c=getchar();
 29     while((c<'0' || c>'9') && c!='-') c=getchar(); if(c=='-') q=1,c=getchar(); 
 30     while (c>='0' && c<='9') w=w*10+c-'0', c=getchar(); return q ? -w : w;
 31 }
 32 
 33 inline void count(node &q){
 34     q.zsyx|=(q.s && q.y) | (q.z && q.x);
 35     q.zxys|=(q.x && q.y) | (q.z && q.s);
 36     if(!q.s) q.s=(q.zsyx && q.y) | (q.z && q.zxys);
 37     if(!q.x) q.x=(q.zxys && q.y) | (q.z && q.zsyx);
 38     if(!q.z) q.z=(q.zsyx && q.x) | (q.zxys && q.s);
 39     if(!q.y) q.y=(q.x && q.zxys) | (q.s && q.zsyx);
 40 }
 41 
 42 inline node merge(node q,node qq){
 43     node tmp=ini; tmp.z=q.z; tmp.y=qq.y; 
 44     if(!tmp.z) tmp.z=(q.s && qq.s && qq.y && qq.x && q.x);
 45     if(!tmp.y) tmp.y=(q.s && qq.s && q.z && q.x && qq.x);
 46     tmp.s=(q.s && qq.s) | (q.zsyx && qq.zxys);
 47     tmp.x=(q.x && qq.x) | (q.zxys && qq.zsyx);
 48     tmp.zsyx=(q.s && qq.zsyx) | (q.zsyx && qq.x);//!!!
 49     tmp.zxys=(q.x && qq.zxys) | (q.zxys && qq.s);//!!!
 50     count(tmp); 
 51     return tmp;   
 52 }
 53 
 54 inline void query(int root,int l,int r){
 55     if(ql<=l && r<=qr) {
 56     if(!ok) ans=t[root],ok=true;
 57     else ans=merge(ans,t[root]);
 58     return ;
 59     }
 60     int mid=(l+r)>>1,lc=root*2,rc=lc+1; 
 61     if(ql<=mid) query(lc,l,mid);  
 62     if(qr>mid) query(rc,mid+1,r);
 63 }
 64 
 65 inline void update(int root,int l,int r){    
 66     if(l==r) {
 67     if(CC==1) a[root].s=type;  else if(CC==2) a[root].x=type;
 68     else if(CC==3) a[root].z=type; else if(CC==4) a[root].y=type;
 69     t[root]=a[root]; count(t[root]);
 70     return ;
 71     }
 72     int mid=(l+r)/2; int lc=root*2,rc=lc+1;
 73     if(pos<=mid) update(lc,l,mid); else update(rc,mid+1,r);
 74     t[root]=merge(t[lc],t[rc]); count(t[root]);
 75 }
 76 inline void build(int root,int l,int r){ a[root].l=t[root].l=l; a[root].r=t[root].r=r; if(l==r) return ; int mid=(l+r)/2; int lc=root*2,rc=lc+1; build(lc,l,mid); build(rc,mid+1,r); }
 77 inline void out(int oo){ if(oo) printf("Y\n"); else printf("N\n"); }
 78 inline void init_query(int l,int r){ ql=l; qr=r; ok=false; query(1,1,n); ans.l=l;ans.r=r; }
 79 inline void work(){
 80     n=getint(); n--; int r1,c1,r2,c2; build(1,1,n);
 81     int acnt=0;
 82     while(1) {
 83     scanf("%s",ch); if(ch[0]=='E') break;
 84     r1=getint(); c1=getint(); r2=getint(); c2=getint();
 85     if(c1>c2) swap(c1,c2),swap(r1,r2);
 86     if(ch[0]=='A') {          
 87         acnt++;
 88         if(acnt==141) {
 89         acnt++;
 90         acnt--;
 91         }
 92         if(c1==c2){//同一列        
 93         if(c1==1) out(t[1].z); else if(c1==n+1) out(t[1].y);
 94         else{
 95             init_query(1,c1-1); t1=ans;
 96             init_query(c1,n);/*!!!*/ t2=ans;
 97             if(t1.y || t2.z) out(1); else out(0);            
 98         }
 99         }
100         else{//不同列
101         if(c1>1) { init_query(1,c1-1); t1=ans; } else t1=ini;
102         if(c2<n+1) { init_query(c2,n); t2=ans; } else t2=ini;
103         init_query(c1,c2-1); 
104         if(!ans.z) ans.z=t1.y | (t1.s && t1.x && t1.z);
105         if(!ans.y) ans.y=t2.z | (t2.s && t2.x && t2.y);
106         count(ans);
107         if(r1==1 && r2==1) out(ans.s);
108         else if(r1==1 && r2==2) out(ans.zsyx);
109         else if(r1==2 && r2==1) out(ans.zxys);
110         else if(r1==2 && r2==2) out(ans.x);
111         }
112     }
113     else{
114         if(ch[0]=='O') type=1; else type=0;
115         if(r1==r2) {//同行
116         pos=c1; if(r1==1) CC=1; else CC=2;
117         update(1,1,n);
118         }
119         else{//同列
120         if(c1<n+1) { pos=c1; CC=3; update(1,1,n); }
121         if(c1>1) { pos=c1-1; CC=4; update(1,1,n); }
122         }
123     }
124     }
125 }
126 
127 int main()
128 {
129     work();
130     return 0;
131 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM