13159:决战

#include <cstdio>
#include <cctype>
#include <cstdlib>
#include <algorithm>
#define ll long long
const int SIZE=1<<21;
char ibuf[SIZE],*iS,*iT;
#define gc() getchar()
template <class T>
void read(T &x)
{
	int f=0;x=0;char c=gc();
	while(!isdigit(c)) f|=c=='-',c=gc();
	while(isdigit(c)) x=x*10+c-'0',c=gc();
	if(f) x=-x;
}
void reads(char *s)
{
	int k=0;char c=gc();
	while(c<'A'||c>'Z') c=gc();
	while((c>='a'&&c<='z')||(c>='A'&&c<='Z')) s[k++]=c,c=gc();
}
const int N=5e4+10;
inline void ckmax(int &x,int y){x=x>y?x:y;}
inline void ckmin(int &x,int y){x=x<y?x:y;}
int n,m,r,root[N];
namespace treap
{
	int ch[N][2],mx[N],mi[N],siz[N],val[N],dat[N],tag[N],reve[N],tot;
	ll sum[N];
	#define ls ch[now][0]
	#define rs ch[now][1]
	void updata(int now)
	{
		sum[now]=sum[ls]+dat[now]+sum[rs];
		siz[now]=siz[ls]+1+siz[rs];
		mx[now]=mi[now]=dat[now];
		if(ls)
		{
			ckmax(mx[now],mx[ls]);
			ckmin(mi[now],mi[ls]);
		}
		if(rs)
		{
			ckmax(mx[now],mx[rs]);
			ckmin(mi[now],mi[rs]);
		}
	}
	void Reverse(int now)
	{
		std::swap(ls,rs),reve[now]^=1;
	}
	void upt(int now,int d)
	{
		dat[now]+=d;
		tag[now]+=d;
		mi[now]+=d;
		mx[now]+=d;
		sum[now]+=d*siz[now];
	}
	void pushdown(int now)
	{
		if(reve[now])
		{
			if(ls) Reverse(ls);
			if(rs) Reverse(rs);
			reve[now]=0;
		}
		if(tag[now])
		{
			if(ls) upt(ls,tag[now]);
			if(rs) upt(rs,tag[now]);
			tag[now]=0;
		}
	}
	void split(int now,int &x,int &y,int k)
	{
		if(!now){x=y=0;return;}
		pushdown(now);
		if(k<=siz[ls])
			y=now,split(ls,x,ch[y][0],k);
		else
			x=now,split(rs,ch[x][1],y,k-siz[ls]-1);
		updata(now);
	}
	int Merge(int x,int y)
	{
		if(!x||!y) return x^y;
		pushdown(x),pushdown(y);
		if(val[x]<val[y])
		{
			ch[x][1]=Merge(ch[x][1],y);
			updata(x);
			return x;
		}
		else
		{
			ch[y][0]=Merge(x,ch[y][0]);
			updata(y);
			return y;
		}
	}
	int New(int d)
	{
		val[++tot]=rand(),siz[tot]=1,sum[tot]=mi[tot]=mx[tot]=dat[tot]=d;
		return tot;
	}
	void ins(int id,int d)
	{
		root[id]=Merge(root[id],New(d));
	}
	ll querysum(int id,int l,int r)
	{
		int x,y,z;
		split(root[id],x,y,r);
		split(x,x,z,l-1);
		ll ret=sum[z];
		root[id]=Merge(x,Merge(z,y));
		return ret;
	}
	int querymi(int id,int l,int r)
	{
		int x,y,z;
		split(root[id],x,y,r);
		split(x,x,z,l-1);
		int ret=mi[z];
		root[id]=Merge(x,Merge(z,y));
		return ret;
	}
	int querymx(int id,int l,int r)
	{
		int x,y,z;
		split(root[id],x,y,r);
		split(x,x,z,l-1);
		int ret=mx[z];
		root[id]=Merge(x,Merge(z,y));
		return ret;
	}
	void modify(int id,int l,int r,int w)
	{
		int x,y,z;
		split(root[id],x,y,r);
		split(x,x,z,l-1);
		upt(z,w);
		root[id]=Merge(x,Merge(z,y));
	}
}
using treap::modify;
using treap::querysum;
using treap::querymi;
using treap::querymx;
using treap::ins;
using treap::Merge;
using treap::split;
using treap::Reverse;
int head[N],to[N<<1],Next[N<<1],cnt;
void add(int u,int v)
{
	to[++cnt]=v,Next[cnt]=head[u],head[u]=cnt;
}
int top[N],ws[N],siz[N],par[N],dep[N],rk[N],num[N];
void dfs(int now)
{
	siz[now]=1;
	dep[now]=dep[par[now]]+1;
	for(int v,i=head[now];i;i=Next[i])
		if((v=to[i])!=par[now])
		{
			par[v]=now;
			dfs(v);
			siz[now]+=siz[v];
			if(siz[ws[now]]<siz[v]) ws[now]=v;
		}
}
int lin,tot[N];
void dfs(int now,int id,int anc)
{
	top[now]=anc;
	num[now]=id;
	rk[now]=++tot[id];
	ins(id,0);
	if(ws[now]) dfs(ws[now],id,anc);
	for(int v,i=head[now];i;i=Next[i])
		if(!num[v=to[i]])
			dfs(v,++lin,v);
}
void modi(int x,int y,int w)
{
	if(dep[x]<dep[y]) std::swap(x,y);
	while(top[x]!=top[y])
	{
		modify(num[x],1,rk[x],w);
		x=par[top[x]];
	}
	if(dep[x]<dep[y]) std::swap(x,y);
	modify(num[x],rk[y],rk[x],w);
}
void qrysum(int x,int y)
{
	ll ret=0;
	while(top[x]!=top[y])
	{
	    if(dep[top[x]]>dep[top[y]])
        {
            ret+=querysum(num[x],1,rk[x]);
            x=par[top[x]];
        }
		else
        {
            ret+=querysum(num[y],1,rk[y]);
            y=par[top[y]];
        }
	}
	if(dep[x]<dep[y]) std::swap(x,y);
	ret+=querysum(num[x],rk[y],rk[x]);
	printf("%lld\n",ret);
}
void qrymx(int x,int y)
{
	int ret=-(1<<30);
	while(top[x]!=top[y])
	{
		if(dep[top[x]]>dep[top[y]])
        {
            ckmax(ret,querymx(num[x],1,rk[x]));
            x=par[top[x]];
        }
		else
        {
            ckmax(ret,querymx(num[y],1,rk[y]));
            y=par[top[y]];
        }
	}
	if(dep[x]<dep[y]) std::swap(x,y);
	ckmax(ret,querymx(num[x],rk[y],rk[x]));
	printf("%d\n",ret);
}
void qrymi(int x,int y)
{
	int ret=1<<30;
	while(top[x]!=top[y])
	{
		if(dep[top[x]]>dep[top[y]])
        {
            ckmin(ret,querymi(num[x],1,rk[x]));
            x=par[top[x]];
        }
		else
        {
            ckmin(ret,querymi(num[y],1,rk[y]));
            y=par[top[y]];
        }
	}
	if(dep[x]<dep[y]) std::swap(x,y);
	ckmin(ret,querymi(num[x],rk[y],rk[x]));
	printf("%d\n",ret);
}
void rev(int x,int y)
{
	int tx=x,ty=y;
	if(dep[x]<dep[y]) std::swap(x,y);
	int rt=0;
	while(top[x]!=top[y])
	{
		int id=num[x],k=rk[x],pre;
		split(root[id],pre,root[id],k);
		rt=Merge(pre,rt);
		x=par[top[x]];
	}
	if(dep[x]<dep[y]) std::swap(x,y);
	int id=num[x],l=rk[y],r=rk[x],a,b,c;
	split(root[id],a,c,r);
	split(a,a,b,l-1);
	rt=Merge(b,rt);
	Reverse(rt);
	x=tx,y=ty;
	if(dep[x]<dep[y]) std::swap(x,y);
	while(top[x]!=top[y])
	{
		int id=num[x],k=rk[x],pre;
		split(rt,rt,pre,treap::siz[rt]-k);
		root[id]=Merge(pre,root[id]);
		x=par[top[x]];
	}
	id=num[x];
	root[id]=Merge(a,Merge(rt,c));
}
int main()
{
	read(n),read(m),read(r);
	for(int u,v,i=1;i<n;i++) read(u),read(v),add(u,v),add(v,u);
	dfs(r);
	dfs(r,++lin,r);
	char op[23];
	for(int x,y,w,i=1;i<=m;i++)
	{
		reads(op),read(x),read(y);
		if(op[0]=='I')
		{
			if(op[2]=='c') read(w),modi(x,y,w);
			else rev(x,y);
		}
		else if(op[0]=='S') qrysum(x,y);
		else
		{
			if(op[1]=='a') qrymx(x,y);
			else qrymi(x,y);
		}
	}
	return 0;
}

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值