• 树链剖分【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));}
    	}
    }
    
  • 相关阅读:
    关于数据库的基础知识
    Oracle数据库的上机作业
    PHP表单处理
    EasyUI DataGrid结合ThinkPHP实现增删改查操作———初学者
    Redis crackit
    nodeppt安装后,phantomjs不能运行了 Bad argument
    redis命令
    eclipse编辑web.xml很慢
    客制化jasperreport导出html的过程
    dynamicreport, JFreeChart
  • 原文地址:https://www.cnblogs.com/-guz/p/9800225.html
Copyright © 2020-2023  润新知