树链剖分【p4315】月下"毛景树"

Description

毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园。 毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校园里。

爬啊爬爬啊爬毛毛虫爬到了一颗小小的“毛景树”下面,发现树上长着他最爱吃的毛毛果~~ “毛景树”上有N个节点和N-1条树枝,但节点上是没有毛毛果的,毛毛果都是长在树枝上的。但是这棵“毛景树”有着神奇的魔力,他能改变树枝上毛毛果的个数:

  • Change k w:将第k条树枝上毛毛果的个数改变为w个。
  • Cover u v w:将节点u与节点v之间的树枝上毛毛果的个数都改变为w个。
  • Add u v w:将节点u与节点v之间的树枝上毛毛果的个数都增加w个。 由于毛毛虫很贪,于是他会有如下询问:
  • Max u v:询问节点u与节点v之间树枝上毛毛果个数最多有多少个。

Input

第一行一个正整数N。

接下来N-1行,每行三个正整数Ui,Vi和Wi,第i+1行描述第i条树枝。表示第i条树枝连接节点Ui和节点Vi,树枝上有Wi个毛毛果。 接下来是操作和询问,以“Stop”结束。

Output

对于毛毛虫的每个询问操作,输出一个答案。

树剖裸题,注意边权转点权,

这里要找到编号为(k)的边所连的深度深的点.

我们把边权传递给下面深度较深的点,是可以保证每个点价值唯一的.

只需要维护区间覆盖和区间最大值即可了.

注意区间覆盖的优先级高于区间加

代码

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cctype>
#define int long long
#define ls o<<1
#define rs o<<1|1
#define R register
#define N 100008
using namespace std;
inline void in(int &x)
{
	int f=1;x=0;char s=getchar();
	while(!isdigit(s)){if(s=='-')f=-1;s=getchar();}
	while(isdigit(s)){x=x*10+s-'0';s=getchar();}
	x*=f;
}
int head[N],tot;
struct cod{int u,v,w,fr;}edge[N<<2];
inline void add(int x,int y,int z)
{
	edge[++tot].u=head[x];
	edge[tot].fr=x;
	edge[tot].v=y;
	edge[tot].w=z;
	head[x]=tot;
}
int size[N],son[N],f[N],depth[N],val[N];
void dfs1(int u,int fa,int dis)
{
	val[u]=dis;f[u]=fa;size[u]=1;depth[u]=depth[fa]+1;
	for(R int i=head[u];i;i=edge[i].u)
	{
		if(edge[i].v==fa)continue;
		dfs1(edge[i].v,u,edge[i].w);
		size[u]+=size[edge[i].v];
		if(son[u]==-1 or size[son[u]]<size[edge[i].v])
			son[u]=edge[i].v;
	}
}
int dfn[N],fdfn[N],idx,top[N];
void dfs2(int u,int t)
{
	top[u]=t;dfn[u]=++idx;fdfn[idx]=u;
	if(son[u]==-1)return;
	dfs2(son[u],t);
	for(R int i=head[u];i;i=edge[i].u)
	{
		if(dfn[edge[i].v])continue;
		dfs2(edge[i].v,edge[i].v);
	}
}
int n;
char s[8];
int tr[N<<2],tg1[N<<2],tg2[N<<2];
inline void up(int o)
{
	tr[o]=max(tr[ls],tr[rs]);
	return;
}
inline void down(int o,int l,int r)
{
	if(tg1[o]>=0)
	{
		tr[ls]=tr[rs]=tg1[ls]=tg1[rs]=tg1[o];
		tg1[o]=-1;tg2[ls]=tg2[rs]=0;
	}
	if(tg2[o])
	{
		tr[ls]+=tg2[o];tr[rs]+=tg2[o];
		tg2[ls]+=tg2[o];tg2[rs]+=tg2[o];
		tg2[o]=0;
	}
}
void build(int o,int l,int r)
{
	tg1[o]=-1;
	if(l==r)
	{
		tr[o]=val[fdfn[l]];
		return;
	}
	int mid=(l+r)>>1;
	build(ls,l,mid);
	build(rs,mid+1,r);
	up(o);
}
void change1(int o,int l,int r,int x,int y,int k)//区间覆盖. 
{
	if(x<=l and y>=r)
	{
		tr[o]=tg1[o]=k;
		tg2[o]=0;
		return;
	}
	down(o,l,r);
	int mid=(l+r)>>1;
	if(x<=mid)change1(ls,l,mid,x,y,k);
	if(y>mid)change1(rs,mid+1,r,x,y,k);
	up(o);
}
void change2(int o,int l,int r,int x,int y,int k)//区间增加. 
{
	if(x<=l and y>=r)
	{
		tr[o]+=k;tg2[o]+=k;
		return;
	}
	down(o,l,r);
	int mid=(l+r)>>1;
	if(x<=mid)change2(ls,l,mid,x,y,k);
	if(y>mid)change2(rs,mid+1,r,x,y,k);
	up(o);
}
int query(int o,int l,int r,int x,int y)
{
	if(x<=l and y>=r)return tr[o];
	down(o,l,r);
	int mid=(l+r)>>1,res=-2147483647;
	if(x<=mid)res=max(res,query(ls,l,mid,x,y));
	if(y>mid)res=max(res,query(rs,mid+1,r,x,y));
	return res;
}
inline void tchange1(int x,int y,int k)
{
	int fx=top[x],fy=top[y];
	while(fx!=fy)
	{
		if(depth[fx]>depth[fy])
		{
			change1(1,1,idx,dfn[fx],dfn[x],k);
			x=f[fx];
		}
		else 
		{
			change1(1,1,idx,dfn[fy],dfn[y],k);
			y=f[fy];
		}
		fx=top[x],fy=top[y];
	}
	if(x==y)return;
	if(dfn[x]>dfn[y])swap(x,y);
	change1(1,1,idx,dfn[x]+1,dfn[y],k);
	return;
}
inline void tchange2(int x,int y,int k)
{
	int fx=top[x],fy=top[y];
	while(fx!=fy)
	{
		if(depth[fx]>depth[fy])
		{
			change2(1,1,idx,dfn[fx],dfn[x],k);
			x=f[fx];
		}
		else 
		{
			change2(1,1,idx,dfn[fy],dfn[y],k);
			y=f[fy];
		}
		fx=top[x],fy=top[y];
	}
	if(x==y)return;
	if(dfn[x]>dfn[y])swap(x,y);
	change2(1,1,idx,dfn[x]+1,dfn[y],k);
	return;
}
inline int tquery(int x,int y)
{
	int fx=top[x],fy=top[y],res=-2147483647;
	while(fx!=fy)
	{
		if(depth[fx]>depth[fy])
		{
			res=max(res,query(1,1,idx,dfn[fx],dfn[x]));
			x=f[fx];
		}
		else 
		{
			res=max(res,query(1,1,idx,dfn[fy],dfn[y]));
			y=f[fy];
		}
		fx=top[x],fy=top[y];
	}
	if(x==y)return res;
	if(dfn[x]>dfn[y])swap(x,y);
	res=max(res,query(1,1,idx,dfn[x]+1,dfn[y]));
	return res;
}
signed main()
{
	in(n);memset(son,-1,sizeof son);
	for(R int i=1,x,y,z;i<n;i++)
	{
		in(x),in(y),in(z);
		add(x,y,z),add(y,x,z);
	}
	dfs1(1,0,0);dfs2(1,1);build(1,1,idx);
	while(1)
	{
		scanf("%s",s);
		if(s[0]=='S')break;
		R int x,y,k;
		if(s[0]=='C' and s[1]=='h')
			{
				in(x),in(k);
				x*=2;
				if(depth[edge[x].fr]>depth[edge[x].v])
					x=edge[x].fr;
				else x=edge[x].v;
				change1(1,1,idx,dfn[x],dfn[x],k);
			}//单点修改 
		else if(s[0]=='C' and s[1]=='o')
			{in(x),in(y),in(k);tchange1(x,y,k);}//区间覆盖 
		else if(s[0]=='A')//区间增加 
			{in(x),in(y),in(k);tchange2(x,y,k);}
		else if(s[0]=='M')
			{in(x),in(y);printf("%lld
",tquery(x,y));}
	}
}
原文地址:https://www.cnblogs.com/-guz/p/9800225.html