BZOJ1984 月下“毛景樹”
阿新 • • 發佈:2018-12-11
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; }