1. 程式人生 > 實用技巧 >洛谷 P4315 月下“毛景樹”

洛谷 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;
}