【UOJ274】【清華集訓2016】溫暖會指引我們前行 LCT
【UOJ274】【清華集訓2016】溫暖會指引我們前行
任務描述
雖然小R住的宿舍樓早已來了暖氣,但是由於某些原因,宿舍樓中的某些窗戶仍然開著(例如廁所的窗戶),這就使得宿舍樓中有一些路上的溫度還是很低。
小R的宿舍樓中有n個地點和一些路,一條路連接了兩個地點,小R可以通過這條路從其中任意一個地點到達另外一個地點。但在剛開始,小R還不熟悉宿舍樓中的任何一條路,所以他會慢慢地發現這些路,他在發現一條路時還會知道這條路的溫度和長度。每條路的溫度都是互不相同的。
小R需要在宿舍樓中活動,每次他都需要從一個地點到達另一個地點。小R希望每次活動時經過一條最溫暖的路徑,最溫暖的路徑的定義為,將路徑上各條路的溫度從小到大排序後字典序最大。即溫度最低的路溫度盡量高,在滿足該條件的情況下,溫度第二低的路溫度盡量高,以此類推。小R不會經過重復的路。由於每條路的溫度互不相同,因此只存在一條最溫暖的路徑。
對於小R的每次活動,你需要求出小R需要走過的路徑總長度。如果小R通過當前發現的路不能完成這次活動,則輸出 −1。
註意本題中的字典序與傳統意義上的字典序定義有所不同,對於兩個序列a,b(a≠b),若a是b的前綴則a的字典序較大,同時可以推出空串的字典序最大。
輸入格式
第一行兩個正整數 n,m。表示小R的宿舍樓中有 n 個地點,共發生了 m 個事件。
接下來 m 行,每行描述一個事件,事件分為三類。
-
find id u v t l 表示小R發現了一條連接u和v之間的路,編號為id。相同id的邊只會出現一次。
-
move u v 表示小R要從u到達
-
change id l 表示從u到v這條邊的長度變為了l(保證在當前時間點這條邊存在)。
輸出格式
對於每個詢問,輸出一行整數,表示最溫暖的路徑長度。
題解:裸題,直接用LCT維護最大生成樹即可。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int maxn=100010; int n,m,tot; struct LCT { int ch[2],fa,rev,v,vn,l,sl; }s[maxn<<2]; int f[maxn],pa[maxn<<2],pb[maxn<<2]; char str[10]; inline bool isr(int x) {return (s[s[x].fa].ch[0]!=x)&&(s[s[x].fa].ch[1]!=x);} inline void pushdown(int x) { if(s[x].rev) { swap(s[x].ch[0],s[x].ch[1]); if(s[x].ch[0]) s[s[x].ch[0]].rev^=1; if(s[x].ch[1]) s[s[x].ch[1]].rev^=1; s[x].rev=0; } } inline int MN(int a,int b) {return s[a].v<s[b].v?a:b;} inline void pushup(int x) { s[x].vn=MN(MN(s[s[x].ch[0]].vn,s[s[x].ch[1]].vn),x); s[x].sl=s[s[x].ch[0]].sl+s[s[x].ch[1]].sl+s[x].l; } inline void rotate(int x) { int y=s[x].fa,z=s[y].fa,d=(x==s[y].ch[1]); if(!isr(y)) s[z].ch[y==s[z].ch[1]]=x; s[x].fa=z,s[y].fa=x,s[y].ch[d]=s[x].ch[d^1]; if(s[x].ch[d^1]) s[s[x].ch[d^1]].fa=y; s[x].ch[d^1]=y; pushup(y),pushup(x); } void updata(int x) { if(!isr(x)) updata(s[x].fa); pushdown(x); } inline void splay(int x) { updata(x); while(!isr(x)) { int y=s[x].fa,z=s[y].fa; if(!isr(y)) { if((x==s[y].ch[0])^(y==s[z].ch[0])) rotate(x); else rotate(y); } rotate(x); } } inline void access(int x) { for(int y=0;x;splay(x),s[x].ch[1]=y,pushup(x),y=x,x=s[x].fa); } inline void maker(int x) { access(x),splay(x),s[x].rev^=1; } inline void link(int x,int y) { maker(y),s[y].fa=x; } inline void cut(int x,int y) { maker(x),access(y),splay(y),s[y].ch[0]=s[x].fa=0,pushup(x),pushup(y); } int find(int x) { return (f[x]==x)?x:(f[x]=find(f[x])); } inline int rd() { int ret=0,f=1; char gc=getchar(); while(gc<‘0‘||gc>‘9‘) {if(gc==‘-‘) f=-f; gc=getchar();} while(gc>=‘0‘&&gc<=‘9‘) ret=ret*10+(gc^‘0‘),gc=getchar(); return ret*f; } int main() { //freopen("bz4736.in","r",stdin); s[0].v=1<<30; n=rd(),m=rd(); int i,a,b,c,e; for(i=1;i<=n;i++) f[i]=i,s[i].v=1<<30,s[i].vn=i; for(i=1;i<=m;i++) { scanf("%s",str); if(str[0]==‘f‘) { e=n+rd()+1,a=pa[e]=rd()+1,b=pb[e]=rd()+1,s[e].v=rd(),s[e].vn=e,s[e].l=s[e].sl=rd(); if(find(a)==find(b)) { maker(a),access(b),splay(b),c=s[s[b].ch[0]].vn; if(s[c].v<s[e].v) cut(c,pa[c]),cut(c,pb[c]),link(a,e),link(b,e); } else f[f[a]]=f[b],link(a,e),link(b,e); } if(str[0]==‘m‘) { a=rd()+1,b=rd()+1; if(find(a)!=find(b)) puts("-1"); else maker(a),access(b),splay(b),printf("%d\n",s[s[b].ch[0]].sl); } if(str[0]==‘c‘) e=n+rd()+1,splay(e),s[e].l=rd(),pushup(e); } return 0; }
【UOJ274】【清華集訓2016】溫暖會指引我們前行 LCT