zoukankan      html  css  js  c++  java
  • 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之间树枝上毛毛果个数最多有多少个。

    解析

    毒瘤题。

    看了讨论才意识到优先级问题,我太菜了。

    首先这是个裸的边树剖。一般来说,我们平时做的树剖都是对一系列点权进行操作,而这题要求我们对一系列边权进行操作。

    点权转化为边权,是一件很简单的事情。我们只需把每个节点(x)(father(x))之间的边权存在(x)的点权上就行了,显然这是不影响正确性的。那么对于一个对(ssim t)的路径操作,我们就只用在原先统计点权的基础上减去(s,t)的LCA的点权就可以了。而树剖给了我们一个方便的优化,统计答案时,最后一步一定有(top[x]=top[y])(设(deep[x]<deep[y])),而且它们处于同一条重链上,那么根据树剖的编号规则,(lca(s,t))正是此时的(x),我们统计(calc(id[x]+1,id[y]))(id[x])为树剖后(x)的编号)即可。


    这一题的毒瘤之处在于区间加和区间覆盖之间的优先级。显然,将区间全部修改为同一个值的优先级大于区间加。

    我们需要这么搞pushdown:

    inline void pushdown(int p)
    {	
    	if(t[p].rem!=-1){//区间覆盖为某一值的tag
    		t[p<<1].max=t[p].rem;
    		t[p<<1|1].max=t[p].rem;
    		t[p<<1].rem=t[p].rem;
    		t[p<<1|1].rem=t[p].rem;
    		t[p<<1].add=0;t[p<<1|1].add=0;
    		t[p].rem=-1;
    	}
    	if(t[p].add){//区间加的tag
    		t[p<<1].max+=t[p].add;
    		t[p<<1|1].max+=t[p].add;
    		t[p<<1].add+=t[p].add;
    		t[p<<1|1].add+=t[p].add;
    		t[p].add=0;
    	}
    }
    

    参考代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<string>
    #include<cstdlib>
    #include<queue>
    #include<vector>
    #define INF 0x3f3f3f3f
    #define PI acos(-1.0)
    #define N 100010
    #define MOD 2520
    #define E 1e-12
    using namespace std;
    inline int read()
    {
    	int f=1,x=0;char c=getchar();
    	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    	while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    	return x*f;
    }
    struct rec{
    	int ver,next,edge;
    }g[N<<1];
    int head[N],tot,n,cnt;
    inline void add(int x,int y,int val)
    {
    	g[++tot].ver=y,g[tot].edge=val;
    	g[tot].next=head[x],head[x]=tot;
    }
    struct tree{
    	int l,r;
    	int max,add,rem;
    }t[N<<2];
    int top[N],id[N],size[N],son[N],fa[N],dep[N],w[N],wt[N];
    struct node{
    	int u,v;
    }a[N];
    inline void pushup(int p){t[p].max=max(t[p<<1].max,t[p<<1|1].max);}
    inline void pushdown(int p)
    {	
    	if(t[p].rem!=-1){
    		t[p<<1].max=t[p].rem;
    		t[p<<1|1].max=t[p].rem;
    		t[p<<1].rem=t[p].rem;
    		t[p<<1|1].rem=t[p].rem;
    		t[p<<1].add=0;t[p<<1|1].add=0;
    		t[p].rem=-1;
    	}
    	if(t[p].add){
    		t[p<<1].max+=t[p].add;
    		t[p<<1|1].max+=t[p].add;
    		t[p<<1].add+=t[p].add;
    		t[p<<1|1].add+=t[p].add;
    		t[p].add=0;
    	}
    }
    inline void build(int p,int l,int r)
    {
    	t[p].l=l,t[p].r=r;t[p].rem=-1;
    	if(l==r){t[p].max=w[l];return;}
    	int mid=(l+r)>>1;
    	build(p<<1,l,mid);
    	build(p<<1|1,mid+1,r);
    	pushup(p);
    }
    inline void change(int p,int l,int r,int val)
    {
    	if(l<=t[p].l&&t[p].r<=r){
    		t[p].max+=val;
    		t[p].add+=val;
    		return;
    	}
    	pushdown(p);
    	int mid=(t[p].l+t[p].r)>>1;
    	if(l<=mid) change(p<<1,l,r,val);
    	if(r>mid) change(p<<1|1,l,r,val);
    	pushup(p);
    }
    inline void Cover(int p,int l,int r,int val)
    {
    	if(l<=t[p].l&&t[p].r<=r){
    		t[p].max=val;
    		t[p].rem=val;t[p].add=0;
    		return;
    	}
    	pushdown(p);
    	int mid=(t[p].l+t[p].r)>>1;
    	if(l<=mid) Cover(p<<1,l,r,val);
    	if(r>mid) Cover(p<<1|1,l,r,val);
    	pushup(p);
    }
    inline int query(int p,int l,int r)
    {
    	if(l<=t[p].l&&t[p].r<=r) return t[p].max;
    	pushdown(p);
    	int mid=(t[p].l+t[p].r)>>1;
    	int val=0;
    	if(l<=mid) val=max(val,query(p<<1,l,r));
    	if(r>mid) val=max(val,query(p<<1|1,l,r));
    	return val;
    }
    inline void dfs1(int x,int f,int deep)
    {
    	size[x]=1,fa[x]=f,dep[x]=deep;
    	int maxson=-1;
    	for(int i=head[x];i;i=g[i].next){
    		int y=g[i].ver,z=g[i].edge;
    		if(y==f) continue;
    		wt[y]=z;
    		dfs1(y,x,deep+1);
    		size[x]+=size[y];
    		if(maxson<size[y]) maxson=size[y],son[x]=y;
    	}
    }
    inline void dfs2(int x,int topf)
    {
    	id[x]=++cnt,top[x]=topf,w[cnt]=wt[x];;
    	if(!son[x]) return;
    	dfs2(son[x],topf);
    	for(int i=head[x];i;i=g[i].next){
    		int y=g[i].ver;
    		if(y==fa[x]||y==son[x]) continue;
    		dfs2(y,y);
    	}
    }
    inline void ichange(int x,int y,int val)
    {
    	while(top[x]!=top[y]){
    		if(dep[top[x]]<dep[top[y]]) swap(x,y);
    		change(1,id[top[x]],id[x],val);
    		x=fa[top[x]];
    	}
    	if(dep[x]>dep[y]) swap(x,y);
    	change(1,id[x]+1,id[y],val);
    }
    inline int iquery(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(1,id[top[x]],id[x]));
    		x=fa[top[x]];
    	}
    	if(dep[x]>dep[y]) swap(x,y);
    	res=max(res,query(1,id[x]+1,id[y]));
    	return res;
    }
    inline void cover(int x,int y,int val)
    {
    	while(top[x]!=top[y]){
    		if(dep[top[x]]<dep[top[y]]) swap(x,y);
    		Cover(1,id[top[x]],id[x],val);
    		x=fa[top[x]];
    	}
    	if(dep[x]>dep[y]) swap(x,y);
    	Cover(1,id[x]+1,id[y],val);
    }
    int main()
    {
    	n=read();
    	for(int i=1;i<n;++i){
    		a[i].u=read(),a[i].v=read();
    		int z=read();
    		add(a[i].u,a[i].v,z),add(a[i].v,a[i].u,z);
    	}
    	dfs1(1,0,1);
    	dfs2(1,1);
    	build(1,1,n);
    	char op[10];
    	int x,y,z;
    	while(~scanf("%s",op)){
    		if(op[0]=='S') return 0;
    		if(op[0]=='M'){
    			x=read(),y=read();
    			printf("%d
    ",iquery(x,y));
    		}
    		if(op[0]=='A'){
    			x=read(),y=read(),z=read();
    			ichange(x,y,z);
    		}
    		if(op[0]=='C'){
    			if(op[1]=='h'){
    				x=read(),z=read();
    				cover(a[x].u,a[x].v,z);
    			}
    			else{
    				x=read(),y=read(),z=read();
    				cover(x,y,z);
    			}
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    第十四周课程总结&实验报告(简单记事本的实现)
    第十三周课程总结
    第十二周课程总结
    第十一周课程总结
    第十周课程总结
    第九周课程总结&实验报告(七)
    第八周课程总结&实验报告(六)
    第七周课程总结&实验报告(五)
    第五周课程总结&实验报告(四)
    2019JAVA课程总结
  • 原文地址:https://www.cnblogs.com/DarkValkyrie/p/11704442.html
Copyright © 2011-2022 走看看