bzoj2631(lct)

lct模板题。

很长时间没有这么错了。。。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<stack>
using namespace std;
const int N=100055;
const int mod=51061;
typedef unsigned int ll;
inline ll read()
{
	ll ans,f=1;char ch;
	while ((ch=getchar())<'0'||ch>'9') if (ch=='-') f=-1;ans=ch-'0';
	while ((ch=getchar())>='0'&&ch<='9') ans=ans*10+ch-'0';
	return ans*f;
}

int n,m;
int fa[N],ch[N][2];
ll size[N],val[N],sum[N],add[N],mul[N];
bool rev[N];
bool isroot(int u)
{
	return ch[fa[u]][0]!=u&&ch[fa[u]][1]!=u;
 } 
void down(int u)
{
	int l=ch[u][0],r=ch[u][1];
	if (rev[u])
	{
		rev[l]^=1;rev[r]^=1;rev[u]^=1;
		swap(ch[u][0],ch[u][1]);
	}
	if (mul[u]!=1)
	{
		mul[l]=mul[l]*mul[u]%mod,mul[r]=mul[r]*mul[u]%mod;
		add[l]=add[l]*mul[u]%mod,add[r]=add[r]*mul[u]%mod;
		sum[l]=sum[l]*mul[u]%mod,sum[r]=sum[r]*mul[u]%mod;
		val[l]=val[l]*mul[u]%mod,val[r]=val[r]*mul[u]%mod;
		mul[u]=1;
	}
	if (add[u])
	{
		add[l]=(add[l]+add[u])%mod,add[r]=(add[r]+add[u])%mod;
		sum[l]=(sum[l]+size[l]*add[u])%mod;
		sum[r]=(sum[r]+size[r]*add[u])%mod;
		val[l]=(val[l]+add[u])%mod,val[r]=(val[r]+add[u])%mod;
		add[u]=0;
	}
}

void up(int x)
{
	int l=ch[x][0],r=ch[x][1];
	size[x]=size[l]+size[r]+1;
	sum[x]=(val[x]+sum[l]+sum[r])%mod;
}
void rot(int x)
{
	int y=fa[x],z=fa[y],l,r;
	if (ch[y][0]==x) l=0;else l=1;r=l^1;
	if (!isroot(y))
		if (ch[z][0]==y) ch[z][0]=x;else ch[z][1]=x;
	fa[x]=z;fa[y]=x;fa[ch[x][r]]=y;
	ch[y][l]=ch[x][r];ch[x][r]=y;
	up(y);	
}
stack<int> s;
void splay(int x)
{
	int y=x,z;
	while (!isroot(y)) s.push(y),y=fa[y];s.push(y);
	while (!s.empty()) down(s.top()),s.pop();
	
	while (!isroot(x))
	{
		y=fa[x],z=fa[y];
		if (!isroot(y))
			if (ch[z][0]==y^ch[y][0]==x) rot(x);else rot(y);
		rot(x);	
	}
	up(x);
}

void access(int u)
{
	int t=0;
	while (u)
	{
		splay(u);
		ch[u][1]=t;
		t=u;u=fa[u];
	}
}
void to_rt(int u)
{
	access(u);splay(u);rev[u]^=1;
}
void link(int u,int v)
{
	to_rt(u);fa[u]=v;
}
void cut(int u,int v)
{
	to_rt(u);access(v);splay(v);fa[u]=ch[v][0]=0;
}

void cut_link()
{
	int u1,v1,u2,v2;
	u1=read();v1=read();u2=read();v2=read();
	cut(u1,v1);link(u2,v2);
}
void link_add()
{
	int u,v;ll c;
	u=read(),v=read(),c=read();
	to_rt(u);access(v);splay(v);
	add[v]=(add[v]+c)%mod;sum[v]=(sum[v]+size[v]*c)%mod;val[v]=(val[v]+c)%mod;
}

void link_mul()
{
	int u,v;ll c;
	u=read(),v=read(),c=read();
	to_rt(u);access(v);splay(v);
	mul[v]=mul[v]*c%mod;sum[v]=sum[v]*c%mod;val[v]=val[v]*c%mod;add[v]=add[v]*c%mod;
}
void query()
{
	int u,v;
	u=read(),v=read();
	to_rt(u);access(v);splay(v);
	printf("%d\n",sum[v]);
}
int main()
{
	n=read(),m=read();
	for (int i=1;i<=n;i++) mul[i]=val[i]=sum[i]=size[i]=1;
	
	int x,y;
	for (int i=1;i<n;i++)
	{
		x=read(),y=read();
		link(x,y);
	}
	
	char s[3];
	while (m--)
	{
		scanf("%s",s);
		switch(s[0])
		{
			case '+':link_add();break;
			case '-':cut_link();break;
			case '*':link_mul();break;
			case '/':query();break;
		}
	}
	return 0;
}
 

总结

1:split,取u~v这一条链,就是把u转到根,access(v),splay(v)之后就取出这条链了。

2:然后就是标记下传的情况,需要注意,下穿的时候更新的是孩子的数据,当前点事要在之前就是更新过才行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值