• 洛谷 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
    ",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;
    }
    
  • 相关阅读:
    模仿Linux内核kfifo实现的循环缓存
    FFmpeg + SoundTouch实现音频的变调变速
    C++标准库实现WAV文件读写
    PHP写的一个轻量级的DI容器类(转)
    android App抓包工具的应用(转)
    Dell 服务器阵列扩容【经验分享(转)】
    hexo静态博客的安装及应用实践记录
    centos 6.5 升级php到5.6.17版本
    前端框架记录
    Virtual DOM 虚拟DOM的理解(转)
  • 原文地址:https://www.cnblogs.com/fusiwei/p/13848384.html
Copyright © 2020-2023  润新知