標籤:
2049: [Sdoi2008]Cave 洞穴勘測Time Limit: 10 Sec Memory Limit: 259 MB
Submit: 4809 Solved: 2141
[Submit][Status][Discuss]Description
輝輝熱衷於洞穴勘測。某天,他按照地圖來到了一片被標記為JSZX的洞穴群地區。經過初步勘測,輝輝發現這片地區由n個洞穴(分別編號為1到n)以及若干通道組成,並且每條通道串連了恰好兩個洞穴。假如兩個洞穴可以通過一條或者多條通道按一定順序串連起來,那麼這兩個洞穴就是連通的,按順序串連在一起的這些通道則被稱之為這兩個洞穴之間的一條路徑。洞穴都十分堅固無法破壞,然而通道不太穩定,時常因為外界影響而發生改變,比如,根據有關儀器的監測結果,123號洞穴和127號洞穴之間有時會出現一條通道,有時這條通道又會因為某種稀奇古怪的原因被毀。輝輝有一台監測儀器可以即時將通道的每一次改變狀況在輝輝手邊的終端機上顯示:如果監測到洞穴u和洞穴v之間出現了一條通道,終端機上會顯示一條指令 Connect u v 如果監測到洞穴u和洞穴v之間的通道被毀,終端機上會顯示一條指令 Destroy u v 經過長期的艱苦卓絕的手工推算,輝輝發現一個奇怪的現象:無論通道怎麼改變,任意時刻任意兩個洞穴之間至多隻有一條路徑。因而,輝輝堅信這是由於某種本質規律的支配導致的。因而,輝輝更加夜以繼日地堅守在終端機之前,試圖通過通道的改變情況來研究這條本質規律。然而,終於有一天,輝輝在堆積成山的演算紙中崩潰了……他把終端機往地面一砸(終端機也足夠堅固無法破壞),轉而求助於你,說道:“你老兄把這程式寫寫吧”。輝輝希望能隨時通過終端機發出指令 Query u v,向監測儀詢問此時洞穴u和洞穴v是否連通。現在你要為他編寫程式回答每一次詢問。已知在第一條指令顯示之前,JSZX洞穴群中沒有任何通道存在。
Input
第一行為兩個正整數n和m,分別表示洞穴的個數和終端機上出現過的指令的個數。以下m行,依次表示終端機上出現的各條指令。每行開頭是一個表示指令種類的字串s("Connect”、”Destroy”或者”Query”,區分大小寫),之後有兩個整數u和v (1≤u, v≤n且u≠v) 分別表示兩個洞穴的編號。
Output
對每個Query指令,輸出洞穴u和洞穴v是否互相連通:是輸出”Yes”,否則輸出”No”。(不含雙引號)
Sample Input範例輸入1 cave.in
200 5
Query 123 127
Connect 123 127
Query 123 127
Destroy 127 123
Query 123 127
範例輸入2 cave.in
3 5
Connect 1 2
Connect 3 1
Query 2 3
Destroy 1 3
Query 2 3
Sample Output範例輸出1 cave.out
No
Yes
No
範例輸出2 cave.out
Yes
No
HINT
資料說明 10%的資料滿足n≤1000, m≤20000 20%的資料滿足n≤2000, m≤40000 30%的資料滿足n≤3000, m≤60000 40%的資料滿足n≤4000, m≤80000 50%的資料滿足n≤5000, m≤100000 60%的資料滿足n≤6000, m≤120000 70%的資料滿足n≤7000, m≤140000 80%的資料滿足n≤8000, m≤160000 90%的資料滿足n≤9000, m≤180000 100%的資料滿足n≤10000, m≤200000 保證所有Destroy指令將摧毀的是一條存在的通道本題輸入、輸出規模比較大,建議c\c++選手使用scanf和printf進行I\O操作以免逾時
Source
動態樹
[Submit][Status][Discuss]
LCT 本題要注意reverse操作,pushdown
這一步要在splay 的一開始就rev下來,不然TLE
#include<cstdio>#include<cstring>#include<cstdlib>#include<algorithm>#include<functional>#include<iostream>#include<cmath>#include<cctype>#include<ctime>using namespace std;#define For(i,n) for(int i=1;i<=n;i++)#define Fork(i,k,n) for(int i=k;i<=n;i++)#define Rep(i,n) for(int i=0;i<n;i++)#define ForD(i,n) for(int i=n;i;i--)#define RepD(i,n) for(int i=n;i>=0;i--)#define Forp(x) for(int p=pre[x];p;p=next[p])#define Forpiter(x) for(int &p=iter[x];p;p=next[p]) #define Lson (x<<1)#define Rson ((x<<1)+1)#define MEM(a) memset(a,0,sizeof(a));#define MEMI(a) memset(a,127,sizeof(a));#define MEMi(a) memset(a,128,sizeof(a));#define INF (2139062143)#define F (100000007)#define MAXN (10000+10)#define MAXM (200000+10) typedef long long ll;ll mul(ll a,ll b){return (a*b)%F;}ll add(ll a,ll b){return (a+b)%F;}ll sub(ll a,ll b){return (a-b+(a-b)/F*F+F)%F;}void upd(ll &a,ll b){a=(a%F+b%F)%F;}int n,m;class Splay{public:int father[MAXN],siz[MAXN];int ch[MAXN][2];bool root[MAXN];bool rev[MAXN];void mem(int n){MEM(father) MEM(siz) MEM(root)For(i,n+1) siz[i]=1,root[i]=1;root[0]=1;MEM(ch) MEM(rev)}void pushdown(int x){if (!x) return ; if (rev[x]) {if (ch[x][0]) rev[ch[x][0]]^=1;if (ch[x][1]) rev[ch[x][1]]^=1;swap(ch[x][0],ch[x][1]);rev[x]^=1;} }void maintain(int x){siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;}void rotate(int x){int y=father[x],kind=ch[y][1]==x;pushdown(y); pushdown(x);ch[y][kind]=ch[x][!kind];if (ch[y][kind]) {father[ch[y][kind]]=y;}father[x]=father[y];father[y]=x;ch[x][!kind]=y;if (root[y]){root[x]=1;root[y]=0;}else{ch[father[x]][ ch[father[x]][1]==y ] = x;}maintain(y);maintain(x);}void P(int x){if (!root[x]) P(father[x]);pushdown(x);}void splay(int x){P(x);while(!root[x]){int y=father[x];if (y) pushdown(y);int z=father[y];if (z) pushdown(z);if (root[y]) rotate(x);else if ( (ch[y][1]==x)^(ch[z][1]==y) ){rotate(x); rotate(x);} else {rotate(y); rotate(x);}} }int access(int x){int y=0;do{splay(x);if (ch[x][1]) root[ch[x][1]]=1;ch[x][1]=y;if (y) root[y]=0;maintain(x);y = x;x=father [x]; } while (x) ;return y;}void cut(int x){access(x);splay(x);father[ch[x][0]]=0;root[ch[x][0]]=1;ch[x][0]=0;maintain(x);}void join(int x,int y){make_root(x);access(y);splay(y);ch[y][1]=x;father[x]=y;root[x]=0;}void reverse(int x){rev[x]^=1; // 標記記完後迅速處理 }void make_root(int x){access(x);splay(x);reverse(x);pushdown(x);}int get_root(int x){access(x);splay(x);do {pushdown(x);if (ch[x][0]) x=ch[x][0];else break;}while(1);return x;}bool check(int x,int y) {while (father[x]) x=father[x];while (father[y]) y=father[y];return x==y;}}S;char s[30];int main(){//freopen("bzoj2049.in","r",stdin);//freopen(".out","w",stdout); while (scanf("%d%d",&n,&m)==2) {S.mem(n);For(i,m) {int u,v;scanf("%s%d%d",s,&u,&v);switch(s[0]) {case'C':{if (!S.check(u,v)) S.join(u,v);break;}case'D':{S.make_root(u);S.cut(v); break;}case'Q':{if (S.check(u,v)) puts("Yes");else puts("No");break;}}}}return 0;}
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
BZOJ 2049([Sdoi2008]Cave 洞穴勘測-LCT)[Template:LCT]