【bzoj2594】[Wc2006]水管局長資料加強版 link cut tree
阿新 • • 發佈:2019-02-06
好久的坑了,今天終於填上了。
一直想總結一下LCT,結果發現難題都不會做。
離線處理,因為刪邊比較難做,所以我們倒著做變成加邊操作。
問題轉化成加邊維護最小生成樹,用lct維護一下最大的邊是哪一條,一旦新加入的邊形成環了,那麼看一看環上最大的邊和新加入的邊哪個大,如果新加入的邊小,那麼刪除原來的邊,加入這一條邊。
竟然1A,簡直不可思議,不過時間慢成狗。
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #include<iostream> #define maxn 1500010 using namespace std; struct yts { int x,y,id,z; int tag; }e[1000010]; struct yts1 { int op,x,y,ans,id; }q[100010]; int fa[maxn],ch[maxn][2],val[maxn],mx[maxn]; bool rev[maxn]; int f[100010]; int n,m,T,tot,num; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } bool cmp1(yts x,yts y) { return x.x<y.x || (x.x==y.x && x.y<y.y); } int find(int x,int y) { int l=1,r=m,ans; while (l<=r) { int mid=(l+r)/2; if (e[mid].x==x && e[mid].y==y) return mid; if (e[mid].x<x || (e[mid].x==x && e[mid].y<y)) ans=mid,l=mid+1; else r=mid-1; } return ans; } bool cmp2(yts x,yts y) { return x.z<y.z; } bool cmp3(yts x,yts y) { return x.id<y.id; } int dir(int x) { return x==ch[fa[x]][1]; } int isroot(int x) { return !(x==ch[fa[x]][0] || x==ch[fa[x]][1]); } void push_up(int x) { mx[x]=x; if (val[mx[ch[x][0]]]>val[mx[x]]) mx[x]=mx[ch[x][0]]; if (val[mx[ch[x][1]]]>val[mx[x]]) mx[x]=mx[ch[x][1]]; } void reverse(int x) { rev[x]^=1; swap(ch[x][0],ch[x][1]); } void push_down(int x) { if (rev[x]) { if (ch[x][0]) reverse(ch[x][0]); if (ch[x][1]) reverse(ch[x][1]); rev[x]^=1; } } void rotate(int x) { int y=fa[x],z=fa[y],b=dir(x),a=ch[x][!b],c=dir(y); if (!isroot(y)) ch[z][c]=x; fa[x]=z;fa[y]=x;ch[x][!b]=y;ch[y][b]=a; if (a) fa[a]=y; push_up(y);push_up(x); } void down(int x) { if (!isroot(x)) down(fa[x]); push_down(x); } void splay(int x) { down(x); while (!isroot(x)) { int y=fa[x]; if (isroot(y)) rotate(x); else { int b=dir(x),c=dir(y); if (b^c) { rotate(x);rotate(x); } else { rotate(y);rotate(x); } } } } void access(int x) { for (int y=0;x;y=x,x=fa[x]) { splay(x); ch[x][1]=y; push_up(x); } } void make_root(int x) { access(x); splay(x); reverse(x); } void cut(int x,int y) { make_root(x); access(x); splay(y); fa[y]=0; } void link(int x,int y) { make_root(x); fa[x]=y; } int query(int x,int y) { make_root(x); access(y); splay(y); return mx[y]; } int find(int x) { if (f[x]==x) return x; else return f[x]=find(f[x]); } int main() { n=read();m=read();T=read(); for (int i=1;i<=m;i++) {e[i].x=read();e[i].y=read();e[i].z=read();if (e[i].x>e[i].y) swap(e[i].x,e[i].y);} sort(e+1,e+m+1,cmp2); for (int i=1;i<=m;i++) {e[i].id=i;val[i+n]=e[i].z;mx[i+n]=i+n;} sort(e+1,e+m+1,cmp1); for (int i=1;i<=T;i++) { q[i].op=read();q[i].x=read();q[i].y=read(); if (q[i].x>q[i].y) swap(q[i].x,q[i].y); if (q[i].op==2) { int x=find(q[i].x,q[i].y); q[i].id=e[x].id; e[x].tag=1; } } sort(e+1,e+m+1,cmp3); for (int i=1;i<=n;i++) f[i]=i; for (int i=1;i<=m;i++) if (!e[i].tag) { int f1=find(e[i].x),f2=find(e[i].y); if (f1!=f2) { num++; link(e[i].x,i+n);link(e[i].y,i+n); f[f1]=f2; if (num==n-1) break; } } for (int i=T;i>=1;i--) { if (q[i].op==1) q[i].ans=val[query(q[i].x,q[i].y)]; else { int x=query(q[i].x,q[i].y); if (e[q[i].id].z<val[x]) cut(e[x-n].x,x),cut(e[x-n].y,x),link(q[i].x,q[i].id+n),link(q[i].y,q[i].id+n); } } for (int i=1;i<=T;i++) if (q[i].op==1) printf("%d\n",q[i].ans); return 0; }