[WC2006]水管局长 时间倒流LCT维护MST

题目链接:[WC2006]水管局长 时间倒流LCT维护MST


就和普通LCT维护MST一样,只不过我们最开始不加边,先离线之后时间倒流。

然后看成加边操作,维护链上最大值的编号,每次比较链上最大值和当前加入的值选择是否更换即可。


AC代码:

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include
//#define int long long
using namespace std;
#define ls(x) t[x].ch[0]
#define rs(x) t[x].ch[1]
const int N=2e5+10;
int cnt,st[N];
int n,m,q,w[N<<1],idx,res[N];
struct edge{int x,y,z;}e[N];
struct query{int op,x,y;}p[N];	
struct node{int ch[2],fa,re,mx,id;}t[N];
int cmp(edge a,edge b){return a.z<b.z;}
inline void push_up(int p){
	t[p].id=p,t[p].mx=w[p];
	if(t[ls(p)].mx>t[p].mx)	t[p].id=t[ls(p)].id,t[p].mx=t[ls(p)].mx;
	if(t[rs(p)].mx>t[p].mx)	t[p].id=t[rs(p)].id,t[p].mx=t[rs(p)].mx;
}
inline void push_re(int p){swap(ls(p),rs(p)); t[p].re^=1;}
inline void push_down(int p){
	if(!t[p].re)	return;
	if(ls(p))	push_re(ls(p));	if(rs(p))	push_re(rs(p)); t[p].re^=1;
}
inline bool isroot(int x){return ls(t[x].fa)!=x&&rs(t[x].fa)!=x;}
inline void rotate(int x){
	int y=t[x].fa,z=t[y].fa,k=rs(y)==x,w=t[x].ch[!k];
	if(!isroot(y))	t[z].ch[rs(z)==y]=x; t[x].ch[!k]=y; t[y].ch[k]=w;
	if(w)	t[w].fa=y; t[y].fa=x; t[x].fa=z;	push_up(y);
}
inline void splay(int x){
	cnt=1;	st[cnt]=x; int y=x;
	while(!isroot(y))	st[++cnt]=y=t[y].fa;
	while(cnt)	push_down(st[cnt--]);
	while(!isroot(x)){
		int y=t[x].fa,z=t[y].fa;
		if(!isroot(y))	rotate((ls(y)==x)^(ls(z)==y)?x:y); rotate(x);
	}push_up(x);
}
inline void access(int x){
	for(int y=0;x;x=t[y=x].fa) splay(x),rs(x)=y,push_up(x); 
}
inline void makeroot(int x){
	access(x); splay(x); push_re(x);
}
inline void split(int x,int y){
	makeroot(x); access(y); splay(y);
}
int find(int x){
	access(x);	splay(x);	while(t[x].ch[0])	push_down(x),x=t[x].ch[0];
	splay(x);	return x;
}
inline void link(int x,int y){
	makeroot(x);	t[x].fa=y;
}
inline void cut(int x,int y){
	split(x,y);	t[x].fa=ls(y)=0;
}
signed main(){
	cin>>n>>m>>q;	map<pair<int,int>,int> mp,ep;	idx=n;
	for(int i=1;i<=m;i++){
		cin>>e[i].x>>e[i].y>>e[i].z;
		if(e[i].x>e[i].y)	swap(e[i].x,e[i].y);
		ep[{e[i].x,e[i].y}]=e[i].z;
	}
	sort(e+1,e+1+m,cmp);
	for(int i=1;i<=q;i++){
		scanf("%d %d %d",&p[i].op,&p[i].x,&p[i].y);
		if(p[i].x>p[i].y)	swap(p[i].x,p[i].y);
		if(p[i].op==2)	mp[{p[i].x,p[i].y}]=1;
	}
	for(int i=1;i<=m;i++){
		if(mp[{e[i].x,e[i].y}])	continue;
		if(find(e[i].x)==find(e[i].y))	continue;
		w[++idx]=e[i].z;	link(e[i].x,idx),link(idx,e[i].y);
	}
	for(int i=q;i>=1;i--){
		if(p[i].op==2){
			int x=p[i].x,y=p[i].y;	w[++idx]=ep[{x,y}];
			if(find(x)!=find(y))	link(x,idx),link(idx,y);
			else{
				split(x,y);	int now=t[y].id;
				if(t[now].mx<=w[idx])	continue;
				splay(now);
				t[ls(now)].fa=t[rs(now)].fa=0;
				link(x,idx),link(idx,y);
			}
		}else	split(p[i].x,p[i].y),res[i]=w[t[p[i].y].id];
	}
	for(int i=1;i<=q;i++)	if(p[i].op==1)	printf("%d\n",res[i]);
	return 0;
}

你可能感兴趣的:(Link_Cut_Tree)