bzoj2959: 长跑

3 篇文章 0 订阅

又看了一下LCT,复杂度还是不懂,怎么样均摊O(longn)???感觉一写残就退化了。。。

于是回顾了一下板子,总算是过了。。原树上的父亲大概是没有记吧。。

不知道为什么find改成这样会T。。TAT

int find(int x)
{
	acc(x);splay(x);
	while(c[x][0])x=c[x][0];
	return x;
}

#include<iostream>
#include<cstdio>
#include<algorithm>
#define N 150005
using namespace std;
int n,m,a[N],Fa[N];
int read()
{
    int x=0,f=1;char c=getchar();
    for(;c<'0'||c>'9';c=getchar())if(c=='-')f=-1;
    for(;c>='0'&&c<='9';c=getchar())x=x*10+c-'0';
    return x*f;
}
int GetFa(int x){return Fa[x]==x?x:Fa[x]=GetFa(Fa[x]);}
struct LCT
{
	int c[N][2],fa[N],p[N];
	int v[N],sum[N];
	bool rev[N];
	int find(int x){return p[x]==x?x:p[x]=find(p[x]);}
	bool Root(int x){return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;}
	void up(int x)
	{
		int l=c[x][0],r=c[x][1];
		sum[x]=v[x]+sum[l]+sum[r];
	}
	void down(int x)
	{	
		if (!x||!rev[x]) return;
		rev[c[x][0]]^=1,rev[c[x][1]]^=1;
		swap(c[x][0],c[x][1]);rev[x]=0;
	}
	void pushdown(int x){if(!Root(x))pushdown(fa[x]);down(x);}
	void rotate(int x)
	{
		int y=fa[x],z=fa[y],l=(c[y][0]!=x),r=l^1;
		if (!Root(y)){if (c[z][0]==y)c[z][0]=x;else c[z][1]=x;}
		fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
		c[y][l]=c[x][r];c[x][r]=y;up(y);up(x);
	}
	void splay(int x)
	{
		for (pushdown(x);!Root(x);rotate(x))
		{
			int y=fa[x],z=fa[y];
			if (!Root(y))
				{if (c[y][0]==x^c[z][0]==y)rotate(x);else rotate(y);}
		}
	}
	void acc(int x){for(int t=0;x;t=x,x=GetFa(fa[x]))splay(x),c[x][1]=t,fa[t]=x,up(x);}
	void MRt(int x){acc(x);splay(x);rev[x]^=1;}
	void link(int x,int y){MRt(x);fa[x]=y;p[find(x)]=y;}
	void mdy(int x,int y){splay(x);v[x]+=y;up(x);}
	int qry(int x,int y){MRt(x);acc(y);splay(y);return sum[y];}
	void bing(int x,int y)
	{
		down(x);Fa[x]=y;
		if (x!=y) v[y]+=v[x];
		if (c[x][0]) bing(c[x][0],y);
		if (c[x][1]) bing(c[x][1],y);
		c[x][0]=c[x][1]=0;
	}
	void add(int x,int y)
	{
		x=GetFa(x),y=GetFa(y);
		if (x!=y)
		{
			if (find(x)==find(y))
				MRt(x),acc(y),splay(y),bing(y,y);
			else link(x,y);
		}
	}
}T;
int main()
{
	n=read();m=read();
	for (int i=1;i<=n;i++)
		a[i]=read(),T.mdy(i,a[i]),Fa[i]=i,T.p[i]=i;
	while(m--)
	{
		int p=read(),x=read(),y=read();
		switch(p)
		{
			case 1:T.add(x,y);break;
			case 2:T.mdy(GetFa(x),y-a[x]);a[x]=y;break;
			case 3:x=GetFa(x);y=GetFa(y);
				if(T.find(x)==T.find(y))
					printf("%d\n",T.qry(x,y));
				else puts("-1");break;
		}
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值