1. 程式人生 > >BZOJ1984 月下“毛景樹”

BZOJ1984 月下“毛景樹”

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