1. 程式人生 > >[BZOJ2594][Wc2006]水管局長資料加強版(kruskal+lct)

[BZOJ2594][Wc2006]水管局長資料加強版(kruskal+lct)

題目描述

傳送門

題解

寫lct就應該有那種誓死不看板子的氣魄。

這道題思路還是很清晰的,維護一棵最小生成樹,每一次找樹鏈上權值最大的邊
刪邊變成倒序加邊
最開始的時候用沒有刪的邊kruskal直接最小生成樹
動態的話就是維護一棵lct,每一次加邊的時候先找樹鏈上的最大邊,如果最大邊大於當前邊就把最大邊砍掉,把當前邊加進去
lct一遍敲√然而預處理錯了,gg

程式碼

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std; int n,m,q,sz,L[100005],R[100005]; struct data{int x,y,z,opt;}e[1000005],t[100005]; int fa[100005],tot,point[1100005],nxt[2200005],v[2200005]; int f[1100005],ch[1100005][2],val[1100005],maxn[1100005],rev[1100005],stack[1100005],pt[1100005][2],ans[100005]; //---------------------init-------------------------- int read() { int x=0;char ch=getchar(); while
(ch<'0'||ch>'9') ch=getchar(); while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x; } int cmpxy(data a,data b) { return a.x<b.x||(a.x==b.x&&a.y<b.y); } int dvd(int l,int r,int x) { int mid; while (l<=r) { mid=(l+r)>>1; if
(e[mid].y==x) return mid; else if (e[mid].y>x) r=mid-1; else l=mid+1; } } int cmpoptz(data a,data b) { return a.opt<b.opt||(a.opt==b.opt&&a.z<b.z); } int ufs(int x) { if (x==fa[x]) return x; fa[x]=ufs(fa[x]); return fa[x]; } void adde(int x,int y) { ++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; ++tot; nxt[tot]=point[y]; point[y]=tot; v[tot]=x; } void dfs(int x,int fa) { if (fa) f[x]=fa; for (int i=point[x];i;i=nxt[i]) if (v[i]!=fa) dfs(v[i],x); } //--------------------lct----------------------------- bool isroot(int x) { return ch[f[x]][0]!=x&&ch[f[x]][1]!=x; } int get(int x) { return ch[f[x]][1]==x; } void update(int x) { int loc=x; if (ch[x][0]) { if (val[maxn[ch[x][0]]]>val[loc]) loc=maxn[ch[x][0]]; } if (ch[x][1]) { if (val[maxn[ch[x][1]]]>val[loc]) loc=maxn[ch[x][1]]; } maxn[x]=loc; } void pushdown(int x) { if (x&&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]=0; } } void rotate(int x) { int old=f[x],oldf=f[old],wh=get(x); if (!isroot(old)) ch[oldf][ch[oldf][1]==old]=x; f[x]=oldf; ch[old][wh]=ch[x][wh^1]; if (ch[old][wh]) f[ch[old][wh]]=old; ch[x][wh^1]=old; f[old]=x; update(old); update(x); } void splay(int x) { int top=0;stack[++top]=x; for (int i=x;!isroot(i);i=f[i]) stack[++top]=f[i]; for (int i=top;i;--i) pushdown(stack[i]); for (int fa;!isroot(x);rotate(x)) if (!isroot(fa=f[x])) rotate((get(x)==get(fa))?fa:x); } void access(int x) { int t=0; for (;x;t=x,x=f[x]) { splay(x); ch[x][1]=t; update(x); } } void reverse(int x) { access(x); splay(x); rev[x]^=1; } int find(int x) { access(x); splay(x); while (ch[x][0]) x=ch[x][0]; return x; } void link(int x,int y) { reverse(x); f[x]=y; splay(x); } void cut(int x,int y) { reverse(x); access(y); splay(y); ch[y][0]=f[x]=0; } //-----------------operation-------------------------- int query(int x,int y) { reverse(x); access(y); splay(y); return maxn[y]; } void add(int x,int y,int z) { if (find(x)==find(y)) { int loc=query(x,y); if (val[loc]<=z) return; cut(loc,pt[loc][0]); cut(loc,pt[loc][1]); } ++sz; val[sz]=z; pt[sz][0]=x,pt[sz][1]=y; link(x,sz); link(y,sz); } //---------------------main--------------------------- int main() { n=read();m=read();q=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,cmpxy); L[e[1].x]=1;R[e[m].x]=m; for (int i=2;i<=m;++i) if (e[i-1].x!=e[i].x) R[e[i-1].x]=i-1,L[e[i].x]=i; for (int i=1;i<=q;++i) { t[i].opt=read(),t[i].x=read(),t[i].y=read(); if (t[i].x>t[i].y) swap(t[i].x,t[i].y); if (t[i].opt==2) { int loc=dvd(L[t[i].x],R[t[i].x],t[i].y); t[i].z=e[loc].z; e[loc].opt=1; } } sort(e+1,e+m+1,cmpoptz); int cnt=0; for (int i=1;i<=n;++i) fa[i]=i; sz=n; for (int i=1;i<=m;++i) if (!e[i].opt) { int f1=ufs(e[i].x),f2=ufs(e[i].y); if (f1!=f2) { ++sz;val[sz]=e[i].z; pt[sz][0]=e[i].x; pt[sz][1]=e[i].y; adde(e[i].x,sz); adde(e[i].y,sz); fa[f1]=f2; } if (cnt==n-1) break; } else break; dfs(1,0); for (int i=q;i>=1;--i) { if (t[i].opt==1) { int loc=query(t[i].x,t[i].y); ans[i]=val[loc]; } else add(t[i].x,t[i].y,t[i].z); } for (int i=1;i<=q;++i) if (t[i].opt==1) printf("%d\n",ans[i]); }