LCT--luogu P2173 [ZJOI2012]网络

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sizeof_you/article/details/84327463

传送门

L C T LCT 裸题,开 c c l c t lct 就好了
板子还是不太熟 q w q qwq

不过这道题的修改边的操作还是比较有意思的
一开始写的复杂而且还不太对,改了之后就 A A

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define N 10005
#define M 100005
#define C 12
#define ls ch[c][x][0]
#define rs ch[c][x][1]
#define fa f[c][x]
#define int long long
using namespace std;

inline int rd(){
	int x=0,f=1;char c=' ';
	while(c<'0' || c>'9') f=c=='-'?-1:1,c=getchar();
	while(c<='9' && c>='0') x=x*10+c-'0',c=getchar();
	return x*f;
}
inline int max(int x,int y){return x>y?x:y;}

namespace lct{
	int f[C][N],ch[C][N][2],rev[C][N],sum[C][N],val[N],d[C][N];
	inline int get(int c,int x){return ch[c][fa][1]==x;}
	inline void update(int c,int x)
		{sum[c][x]=max(sum[c][ls],max(val[x],sum[c][rs]));}
	inline int isrt(int c,int x)
		{return ch[c][fa][0]!=x && ch[c][fa][1]!=x;}
	inline void rever(int c,int x){rev[c][x]^=1;swap(ls,rs);}
	inline void pushdown(int c,int x){
		if(rev[c][x]){
			if(ls) rever(c,ls);
			if(rs) rever(c,rs);
			rev[c][x]=0;
		}
	}
	void pushup(int c,int x){
		if(!isrt(c,x)) pushup(c,fa);
		pushdown(c,x);
	}
	inline void rotate(int c,int x){
		int old=f[c][x],oldf=f[c][old],wh=get(c,x);
		if(!isrt(c,old)) ch[c][oldf][get(c,old)]=x;
		f[c][x]=oldf; f[c][ch[c][x][wh^1]]=old;
		ch[c][old][wh]=ch[c][x][wh^1]; ch[c][x][wh^1]=old;
		f[c][old]=x; update(c,old); update(c,x);
	}
	inline void splay(int c,int x){
		pushup(c,x);// 
		for(;!isrt(c,x);rotate(c,x))
			if(!isrt(c,fa))
				rotate(c,get(c,x)==get(c,fa)?fa:x);
	}
	inline void access(int c,int x){
		for(int y=0;x;y=x,x=fa) splay(c,x),rs=y,update(c,x);
	}
	inline void makeroot(int c,int x){
		access(c,x); splay(c,x); rever(c,x);
	}
	inline int findroot(int c,int x){
		access(c,x); splay(c,x);
		while(ls) pushdown(c,x),x=ls;//pushdown
		return x;
	}
	inline void split(int c,int x,int y){
		makeroot(c,x); access(c,y); splay(c,y);
	}
	inline void link(int c,int x,int y){
		d[c][x]++; d[c][y]++;
		makeroot(c,x); f[c][x]=y; splay(c,x);
	}
	inline bool check(int c,int x,int y){
		return ch[c][y][0]==x && !rs;
	}
	inline void cut(int c,int x,int y){
		split(c,x,y);
		if(check(c,x,y)){
			d[c][x]--; d[c][y]--;
			fa=ch[c][y][0]=0,update(c,y);
		}
	}
	
}using lct::findroot;

int n,m,c,q;

inline void solve(int x,int y,int z){
	for(int i=0;i<c;i++){
		lct::split(i,x,y);
		if(!lct::check(i,x,y)) continue;
		if(i==z) {puts("Success.");return;}
		if(lct::d[z][x]>1 || lct::d[z][y]>1){
			puts("Error 1."); return;
		}
		if(findroot(z,x)==findroot(z,y)){
			puts("Error 2."); return;
		}
		lct::cut(i,x,y); lct::link(z,x,y);
		puts("Success."); return;
	} puts("No such edge."); return;
}

int x,y,z,opt;

signed main(){
	n=rd(); m=rd(); c=rd(); q=rd();
	for(int i=1;i<=n;i++) lct::val[i]=rd();
	for(int i=1;i<=m;i++){
		x=rd(),y=rd(),z=rd();
		if(findroot(z,x)!=findroot(z,y)) lct::link(z,x,y);
	}
	while(q--){
		opt=rd();
		if(opt==0){
			x=rd(),y=rd(); lct::val[x]=y;
			for(int i=0;i<c;i++){
				lct::access(i,x); 
				lct::splay(i,x); lct::update(i,x);
			}
		}
		if(opt==1){
			x=rd(),y=rd(),z=rd();
			solve(x,y,z);
		}
		if(opt==2){
			x=rd(),y=rd(),z=rd(); lct::split(x,y,z);
			if(findroot(x,y)!=findroot(x,z)) puts("-1");
			else printf("%lld\n",lct::sum[x][z]);
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/sizeof_you/article/details/84327463