BZOJ1984 月下“毛景树”

版权声明: https://blog.csdn.net/DancingZ/article/details/82828185

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

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

Sample Input

4

1 2 8

1 3 7

3 4 9

Max 2 4

Cover 2 4 5

Add 1 4 10

Change 1 16

Max 2 4

Stop

Sample Output

9 16

Hint

  1<=N<=100,000,操作+询问数目不超过100,000。
  保证在任意时刻,所有树枝上毛毛果的个数都不会超过10^9个。

据说是树剖的模板题,但是我觉得这个边操作树剖夹点有点不好搞,就换成lct吧。

维护的标记有点恶心~没有什么值得注意的地方。

ps:debug程序就不删了

#include<bits/stdc++.h>
using namespace std;
#define show_memory(x) cout<<sizeof(x)/(1024*1024*1.0)
const int Maxn=200005;
int n,l[Maxn],r[Maxn];
struct Splay{
    int v[Maxn],mx[Maxn],cov[Maxn],tag[Maxn];
    int p[Maxn],ch[2][Maxn];
    bool rev[Maxn];
    #define ls(x) ch[0][x]
    #define rs(x) ch[1][x]
    inline bool isroot(int x){
        return (ls(p[x])^x)&&(rs(p[x])^x);
    }
    inline void maintain(int x){
		mx[x]=v[x];
		if(ls(x))mx[x]=max(mx[x],mx[ls(x)]);
		if(rs(x))mx[x]=max(mx[x],mx[rs(x)]);
    }
    inline void rotate(int x){
        int f=p[x],gf=p[f],tp=rs(f)==x,son=ch[!tp][x];
        if(!isroot(f))ch[rs(gf)==f][gf]=x;p[x]=gf;
        ch[tp][p[son]=f]=son,maintain(f);
        ch[!tp][p[f]=x]=f,maintain(x);
    }
    inline void pushdown(int x){
        if(rev[x]){
            rev[ls(x)]^=1,rev[rs(x)]^=1;
            swap(ls(x),rs(x));
            rev[x]^=1;
        }
        if(cov[x]){
            cov[ls(x)]=cov[rs(x)]=cov[x];
            if(ls(x)>n)v[ls(x)]=cov[x];
            if(rs(x)>n)v[rs(x)]=cov[x];
            mx[ls(x)]=mx[rs(x)]=cov[x];
            cov[x]=tag[ls(x)]=tag[rs(x)]=0;
        }
        if(tag[x]){
            if(ls(x)>n)v[ls(x)]+=tag[x];
            if(rs(x)>n)v[rs(x)]+=tag[x];
            tag[ls(x)]+=tag[x];mx[ls(x)]+=tag[x];
			tag[rs(x)]+=tag[x];mx[rs(x)]+=tag[x];
            tag[x]=0;
        }
    }
    int top,s[Maxn];
    inline void splay(int x){
        s[++top]=x;for(int i=x;!isroot(i);i=p[i])s[++top]=p[i];
        while(top)pushdown(s[top--]);
        while(!isroot(x)){
            if(!isroot(p[x])&&((rs(p[p[x]])==p[x])==(rs(p[x])==x)))rotate(p[x]);
            rotate(x);
        }
    }
    inline void init(int x,int val){
        p[x]=ls(x)=rs(x)=0;
        v[x]=mx[x]=val;
    }
    /*
    inline void debug(int x){
    	if(!x)return ;
    	pushdown(x);
		debug(ls(x)),debug(rs(x));
		maintain(x);
		cout<<"idx: "<<x<<" lson:"<<ls(x)<<" rson:"<<rs(x)<<" val:"<<v[x]<<" Max:"<<mx[x]<<" add:"<<tag[x]<<" cov:"<<cov[x]<<"\n";
	}
	inline void print(){
		for(int x=1;x<=n*2-1;++x){
			cout<<"idx: "<<x<<" lson:"<<ls(x)<<" rson:"<<rs(x)<<" fa:"<<p[x]<<" val:"<<v[x]<<" Max:"<<mx[x]<<" add:"<<tag[x]<<" cov:"<<cov[x]<<"\n";
		}
		cout<<"\n";
	}
	*/
};
struct LinkCutTree{
    Splay splay;
    inline void access(int x){
        for(int lastx=0;x;lastx=x,x=splay.p[x])
            splay.splay(x),splay.rs(x)=lastx,splay.maintain(x);
    }
    inline void makeroot(int x){
        access(x),splay.splay(x),splay.rev[x]^=1;
    }
    inline void link(int x,int y){
        makeroot(x),splay.p[x]=y;
    }
    inline void split(int x,int y){
        makeroot(x),access(y),splay.splay(y);
    }
    inline void cut(int x,int y){
        split(x,y);splay.p[x]=splay.ls(y)=0;
        splay.maintain(y);
    }
    inline void init(int x,int val){
        splay.init(x,val);
    }
}lct;
inline void getmax(){
    int x,y;scanf("%d%d",&x,&y);
    lct.split(x,y);
    printf("%d\n",lct.splay.mx[y]);
}
inline void change(){
    int x,k;scanf("%d%d",&x,&k);
    lct.cut(l[x+n],x+n),lct.cut(r[x+n],x+n);
    lct.init(x+n,k);
    lct.link(x+n,l[x+n]),lct.link(x+n,r[x+n]);
//    lct.splay.debug(r[x+n]);
}
inline void cover(){
    int x,y,z;scanf("%d%d%d",&x,&y,&z);
    lct.split(x,y);
    lct.splay.cov[y]=lct.splay.mx[y]=z;
    lct.splay.tag[y]=0;
//    lct.splay.debug(y);
}
inline void add(){
    int x,y,z;scanf("%d%d%d",&x,&y,&z);
    lct.split(x,y);
    lct.splay.tag[y]+=z;
    lct.splay.mx[y]+=z;
//    lct.splay.debug(y);
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<n;++i){
        int x,y,z;scanf("%d%d%d",&x,&y,&z);
        lct.init(n+i,z);
        l[n+i]=x,r[n+i]=y;
        lct.link(n+i,x),lct.link(n+i,y);
    }
    while("I'm too handsome~ ~"){
        char op[23];scanf("%s",op+1);
        if(op[1]=='S')break;
        if(op[2]=='a')getmax();
        if(op[2]=='h')change();
        if(op[2]=='o')cover();
        if(op[2]=='d')add();
    }
    /*
    for(int i=1;i<=n*2-1;++i)
        cout<<lct.splay.v[i]<<" ";
    */
    return 0;
}

猜你喜欢

转载自blog.csdn.net/DancingZ/article/details/82828185
今日推荐