【BZOJ】【P2594】【Wc2006】【水管局长数据加强版】【题解】【LCT】

12 篇文章 0 订阅

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2594

其实以前都是背模板……彻底的学习一下LCT

Code:

#include<bits/stdc++.h>
#define V(x) (LCT::pool+x)
#define E(x) (LCT::pool+n+x)
using namespace std;
const int maxn=100010;
const int maxm=1000010;
int n,m,q,anss[maxn];
struct edge{int u,v,w,f,id;bool operator<(const edge o)const{return w<o.w;}}edges[maxm],_edges[maxm];
struct qes{int op,x,y;}Q[maxn];
namespace LCT{
	struct node{
		int rev,val;
		node *c[2],*p,*mx;
		void makerev(){rev^=1;swap(c[0],c[1]);}
		void pd(){if(rev){rev=0;c[0]->makerev();c[1]->makerev();}}
		void rz(){
			mx=this;
			if(mx->val<c[0]->mx->val)mx=c[0]->mx;
			if(mx->val<c[1]->mx->val)mx=c[1]->mx;
		}
		void sets(node *x,int d){pd();(c[d]=x)->p=this;rz();}
		bool d(){return p->c[1]==this;}
		bool rt(){return p->c[0]!=this&&p->c[1]!=this;}
	}*null,pool[maxn+maxm];
	node *newnode(int _val=0){
		static node *x=pool;x->rev=0;x->val=_val;
		x->c[0]=x->c[1]=x->p=null;x->mx=x;
		return x++;
	}
	void init(){
		null=newnode();
		null->c[0]=null->c[1]=null->p=null->mx=null;
		for(int i=1;i<=n;i++)newnode();
		for(int i=1;i<=m;i++)newnode(edges[i].w);
	}
	void rot(node *x){
		node *y=x->p;if(!y->rt())y->p->pd();
		y->pd();x->pd();int d=x->d();
		y->sets(x->c[!d],d);
		if(y->rt())x->p=y->p;
		else y->p->sets(x,y->d());
		x->sets(y,!d);
	}
	void splay(node *x){
		for(;!x->rt();rot(x))if(x->p->rt());
		else if(x->d()==x->p->d())rot(x->p);
		else rot(x);
	}
	node *access(node *x){
		node *y=null;
		for(;x!=null;x=x->p)splay(x),x->sets(y,1),y=x;
		return y;
	}
	void makert(node *x){
		access(x)->makerev();splay(x);
	}
	void link(node *x,node *y){
		makert(x);
		x->p=y;
		access(x);
	}
	void cut(node *x,node *y){
		makert(x);access(y);splay(y);
		y->c[0]=x->p=null;y->rz();
	}
	node *Qmax(node *x,node *y){
		makert(x);access(y);splay(y);
		return y->mx;
	}
}
int getint(){
	int res=0;char c=getchar();
	while(!isdigit(c))c=getchar();
	while(isdigit(c))res=res*10+c-'0',c=getchar();
	return res;
}typedef pair<int,int> pi;map<pi,int>M;
int fa[maxn];
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
int main(){
	scanf("%d%d%d",&n,&m,&q);
	for(int i=1;i<=n;i++)fa[i]=i;
	for(int i=1;i<=m;i++){
		edges[i].u=getint(),edges[i].v=getint(),
		edges[i].w=getint(),edges[i].f=1,edges[i].id=i;
		if(edges[i].u>edges[i].v)swap(edges[i].u,edges[i].v);
		M[pi(edges[i].u,edges[i].v)]=i;	
	}LCT::init();	
	for(int i=1;i<=q;i++){
		Q[i].op=getint();Q[i].x=getint();Q[i].y=getint();	
		if(Q[i].x>Q[i].y)swap(Q[i].x,Q[i].y);
		if(Q[i].op==2)edges[M[pi(Q[i].x,Q[i].y)]].f=0;
	}copy(edges+1,edges+1+m,_edges+1);
	sort(_edges+1,_edges+1+m);
	for(int i=1,k=0;i<=m&&k<n;i++){
		int u=_edges[i].u,v=_edges[i].v;
		if(find(u)==find(v)||!_edges[i].f)continue;
		fa[find(u)]=find(v);k++;
		LCT::link(V(u),E(_edges[i].id));
		LCT::link(E(_edges[i].id),V(v));
	}
	for(int i=q;i;i--){
		int op=Q[i].op,x=Q[i].x,y=Q[i].y;
		if(op==1){
			anss[++anss[0]]=LCT::Qmax(V(x),V(y))->val;
		}else{
			int id=M[pi(x,y)];
			LCT::node *p=LCT::Qmax(V(x),V(y));
			if(p->val>edges[id].w){
				int eid=p-LCT::pool-n;
				LCT::cut(V(edges[eid].u),E(eid));
				LCT::cut(E(eid),V(edges[eid].v));
				LCT::link(V(x),E(id));
				LCT::link(E(id),V(y));
			}	
		}
	}for(int i=anss[0];i;i--)printf("%d\n",anss[i]);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值