uoj 279: [清华集训2016]温暖会指引我们前行

       考前鏼一题保平安,,求明天rp++

       显然就是lct维护动态最大生成树,然后就没了。(写得最短好开心啊>.<)

       另外有没有老司机告诉我findroot的时候不pushdown究竟会不会出问题啊,,在线等,挺急的。

AC代码如下:

#include<bits/stdc++.h>
#define N 400005
#define isrt(x) (c[fa[x]][0]!=x && c[fa[x]][1]!=x)
using namespace std;

int n,m,tp,q[N],e[N][2],c[N][2],fa[N]; bool rev[N];
struct node{ int t,len,mn,sum; }a[N];
void maintain(int x){
	node &o=a[x],&l=a[c[x][0]],&r=a[c[x][1]];
	o.mn=x; o.sum=o.len;
	if (c[x][0]){
		if (a[l.mn].t<a[o.mn].t) o.mn=l.mn; o.sum+=l.sum;
	}
	if (c[x][1]){
		if (a[r.mn].t<a[o.mn].t) o.mn=r.mn; o.sum+=r.sum;
	}
}
void rot(int x){
	int y=fa[x],z=fa[y],l=(c[y][1]==x),r=l^1;
	if (!isrt(y)) c[z][c[z][1]==y]=x;
	fa[x]=z; fa[y]=x; fa[c[x][r]]=y;
	c[y][l]=c[x][r]; c[x][r]=y; maintain(y);
}
void pushdn(int x){
	if (rev[x]){
		swap(c[x][0],c[x][1]);
		rev[c[x][0]]^=1; rev[c[x][1]]^=1; rev[x]=0;
	}
}
void splay(int x){
	int i,y,z; q[tp=1]=x;
	for (i=x; !isrt(i); i=fa[i]) q[++tp]=fa[i];
	while (tp) pushdn(q[tp--]);
	for (; !isrt(x); rot(x)){
		y=fa[x]; z=fa[y];
		if (!isrt(y)) rot(((c[z][0]==y) ^ (c[y][0]==x))?x:y);
	}
	maintain(x);
}
void acss(int x){
	int y=0;
	for (; x; y=x,x=fa[x]){
		splay(x); c[x][1]=y; maintain(x);
	}
}
void makert(int x){
	acss(x); splay(x); rev[x]^=1;
}
void link(int x,int y){
	makert(x); fa[x]=y;
}
void cut(int x,int y){
	makert(x); acss(y); splay(y); c[y][0]=fa[x]=0; maintain(y);
}
int findrt(int x){
	acss(x); splay(x); for (; c[x][0]; x=c[x][0]); return x;
}
int main(){
	scanf("%d%d",&n,&m);
	int i,k,x,y; char ch[10];
	for (i=1; i<=n; i++) a[i].t=1000000000;
	while (m--){
		scanf("%s",ch);
		if (ch[0]=='f'){
			scanf("%d%d%d",&i,&x,&y); i++; x++; y++;
			i+=n; e[i][0]=x; e[i][1]=y;
			scanf("%d%d",&a[i].t,&a[i].len);
			if (findrt(x)!=findrt(y)){
				link(i,x); link(i,y);
			} else{
				makert(x); acss(y); splay(y);
				if (a[a[y].mn].t<a[i].t){
					k=a[y].mn; cut(k,e[k][0]); cut(k,e[k][1]);
					link(i,x); link(i,y);
				}
			}
		} else if (ch[0]=='m'){
			scanf("%d%d",&x,&y); x++; y++;
			if (findrt(x)!=findrt(y)) puts("-1"); else{
				makert(x); acss(y); splay(y);
				printf("%d\n",a[y].sum);
			}
		} else{
			scanf("%d%d",&x,&y); x++;
			x+=n; splay(x); a[x].len=y; maintain(x);
		}
	}
	return 0;
}


by lych

2017.3.22

       

©️2020 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值