您的位置:首页 > 其它

【bzoj2594】[Wc2006]水管局长数据加强版 link cut tree

2016-01-04 21:03 411 查看
好久的坑了,今天终于填上了。

一直想总结一下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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: