洛谷 P4315 月下“毛景树”

洛谷 P4315 月下“毛景树”

洛谷传送门

题目描述

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

爬啊爬爬啊爬毛毛虫爬到了一颗小小的“毛景树”下面,发现树上长着他最爱吃的毛毛果 “毛景树”上有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之间树枝上毛毛果个数最多有多少个。

输入格式

第一行一个正整数N。

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

输出格式

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


题解:

边转点是这道题唯一可以称得上难点的点。

然后就是裸的树剖架线段树。

代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
const int N = 100100;
int ls(int x) {return x << 1;}
int rs(int x) {return x << 1 | 1;}
int n , cnt;
int u[N] , v[N] , w[N] , dep[N] , size[N] , fa[N] , top[N] , hs[N] , a[N] , son[N] , head[N] , dfn[N] , id[N];
int maxn[N << 2] , tag[N << 2] , lazy[N << 2];
char s[10];
struct Edge
{
	int to , dis , nxt;
}e[N << 1];
void add(int from,int to,int dis)
{
	e[++cnt] = (Edge){to,dis,head[from]};
	head[from] = cnt;
}
void get_tree(int now)
{
	size[now] = 1;
	for(int i = head[now];i;i = e[i].nxt)
	{
		int to = e[i].to;
		if(dep[to])	continue;
		a[to] = e[i].dis;
		dep[to] = dep[now] + 1;
		fa[to] = now;
		get_tree(to);
		size[now] += size[to];
		if(size[to] > size[hs[now]])	hs[now] = to;
	}
}
void dfs(int now,int topfa)
{
	dfn[now] = ++cnt;
	id[cnt] = now;
	top[now] = topfa;
	if(hs[now])	dfs(hs[now],topfa);
	for(int i = head[now];i;i = e[i].nxt)
	{
		int to = e[i].to;
		if(to == fa[now] || to == hs[now])	continue;
		dfs(to,to);
	}
}
void build(int p,int l,int r)
{
	if(l == r)
	{
		maxn[p] = a[id[l]];
		return ;
	}
	int mid = (l + r) >> 1;
	build(ls(p),l,mid);
	build(rs(p),mid+1,r);
	maxn[p] = max(maxn[ls(p)],maxn[rs(p)]);
}
void push_down(int p,int l,int r)
{
	if(lazy[p] >= 0)
	{
		tag[ls(p)] = tag[rs(p)] = 0;
		maxn[ls(p)] = maxn[rs(p)] = lazy[ls(p)] = lazy[rs(p)] = lazy[p];
		lazy[p] = -1;
	}
	if(tag[p])
	{
		tag[ls(p)] += tag[p];
		tag[rs(p)] += tag[p];
		maxn[ls(p)] += tag[p];
		maxn[rs(p)] += tag[p];
		tag[p] = 0;
	}
}
int query_max(int p,int l,int r,int x,int y)
{
	if(x <= l && r <= y)	return maxn[p];
	int mid = (l + r) >> 1 , res = 0;
	push_down(p,l,r);
	if(x <= mid)	res = max(res,query_max(ls(p),l,mid,x,y));
	if(y > mid)		res = max(res,query_max(rs(p),mid+1,r,x,y));
	return res;
}
int sec_max(int x,int y)
{
	int res = 0;
	while(top[x] != top[y])
	{
		if(dep[top[x]] < dep[top[y]])	swap(x,y);
		res = max(res , query_max(1,1,n,dfn[top[x]],dfn[x]));
		x = fa[top[x]];
	}
	if(dep[x] < dep[y])	swap(x,y);
	if(dfn[y] < dfn[x])	res = max(res,query_max(1,1,n,dfn[y]+1,dfn[x]));
	return res;
}
void chenge_add(int p,int l,int r,int x,int y,int k)
{
	if(x <= l && r <= y)
	{
		tag[p] += k;
		maxn[p] += k;
		return ;
	}
	int mid = (l + r) >> 1;
	push_down(p,l,r);
	if(x <= mid)	chenge_add(ls(p),l,mid,x,y,k);
	if(y > mid)		chenge_add(rs(p),mid+1,r,x,y,k);
	maxn[p] = max(maxn[ls(p)],maxn[rs(p)]);
}
void sec_add(int x,int y,int z)
{
	while(top[x] != top[y])
	{
		if(dep[top[x]] < dep[top[y]])	swap(x,y);
		chenge_add(1,1,n,dfn[top[x]],dfn[x],z);
		x = fa[top[x]];
	}
	if(dep[x] < dep[y])	swap(x,y);
	if(dfn[y] < dfn[x])	chenge_add(1,1,n,dfn[y]+1,dfn[x],z);
}
void chenge_cover(int p,int l,int r,int x,int y,int k)
{
	if(x <= l && r <= y)	
	{
		maxn[p] = k;
		tag[p] = 0;
		lazy[p] = k;
		return ;
	}
	int mid = (l + r) >> 1;
	push_down(p,l,r);
	if(x <= mid)	chenge_cover(ls(p),l,mid,x,y,k);
	if(y > mid)		chenge_cover(rs(p),mid+1,r,x,y,k);
	maxn[p] = max(maxn[ls(p)],maxn[rs(p)]);
}
void sec_cover(int x,int y,int z)
{
	while(top[x] != top[y])
	{
		if(dep[top[x]] < dep[top[y]])	swap(x,y);
		chenge_cover(1,1,n,dfn[top[x]],dfn[x],z);
		x = fa[top[x]];
	}
	if(dep[x] < dep[y])	swap(x,y);
	if(dfn[y] < dfn[x])	chenge_cover(1,1,n,dfn[y]+1,dfn[x],z);
}
void chenge_(int p,int l,int r,int x,int k)
{
	if(l == r)	
	{
		maxn[p] = k;
		tag[p] = 0;
		lazy[p] = k;
		return ;
	}
	int mid = (l + r) >> 1;
	push_down(p,l,r);
	if(x <= mid)	chenge_(ls(p),l,mid,x,k);
	else	chenge_(rs(p),mid+1,r,x,k);
	maxn[p] = max(maxn[ls(p)],maxn[rs(p)]);
}
int main()
{
	memset(lazy,-1,sizeof lazy);
	scanf("%d",&n);
	for(int i = 1;i < n;i ++)
	{
		scanf("%d%d%d",&u[i],&v[i],&w[i]);
		add(u[i],v[i],w[i]); add(v[i],u[i],w[i]);
	}
	cnt = 0; dep[1] = 1;
	get_tree(1);
	dfs(1,1);
	build(1,1,n);
	for(int i = 1;i < n;i ++)
	{
		if(fa[u[i]] == v[i])	son[i] = u[i];
		else	son[i] = v[i];
	}
	while(1)
	{
		int x , y , z;
		scanf("%s",s);
		if(s[0] == 'S')	
            break;
		if(s[0] == 'M')	
		{
			scanf("%d%d",&x,&y);
			printf("%d\n",sec_max(x,y));
		}
		else	if(s[0] == 'A')
		{
			scanf("%d%d%d",&x,&y,&z);
			sec_add(x,y,z);
		}
		else	if(s[1] == 'o')
		{
			scanf("%d%d%d",&x,&y,&z);
			sec_cover(x,y,z);
		}
		else	
		{
			scanf("%d%d",&x,&y);
			chenge_(1,1,n,dfn[son[x]],y);
		}
	}
	return 0;
}
posted @ 2020-10-20 19:24  Seaway-Fu  阅读(121)  评论(0编辑  收藏  举报