[樹剖]月下“毛景樹”
阿新 • • 發佈:2018-12-18
描述 毛毛蟲經過及時的變形,最終逃過的一劫,離開了菜媽的菜園。 毛毛蟲經過千山萬水,歷盡千辛萬苦,最後來到了小小的紹興一中的校園裡。
爬啊爬爬啊爬毛毛蟲爬到了一顆小小的“毛景樹”下面,發現樹上長著他最愛吃的毛毛果
“毛景樹”上有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之間樹枝上毛毛果個數最多有多少個。
輸入 第一行一個正整數N。
接下來N-1行,每行三個正整數Ui,Vi和Wi,第i+1行描述第i條樹枝。
表示第i條樹枝連線節點Ui和節點Vi,樹枝上有Wi個毛毛果。 接下來是操作和詢問,以“Stop”結束。
輸出 對於毛毛蟲的每個詢問操作,輸出一個答案。
樣例輸入 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
樣例輸出 9 16
提示 【Data Range】 1<=N<=100,000,操作+詢問數目不超過100,000。 保證在任意時刻,所有樹枝上毛毛果的個數都不會超過10^9個。
吐槽: 做DP做成了個智障,來做下資料結構
分析: 樹剖板題,支援單點修改,區間修改,區間覆蓋,區間查詢即可
程式碼:(3.5K不多 )
#include<bits/stdc++.h>
#define ls tr[k].l
#define rs tr[k].r
#define mid (tr[k].l+tr[k].r>>1)
using namespace std;
const int N=100005;
int a[N],tot=0,head[N<<1],nxt[N<<1],vis[N<<1],pt[N],c[N<<1],siz[ N],dep[N],fa[N],top[N],hson[N],dfn[N],id[N],cnt=0;
inline void add(int x,int y,int z){vis[++tot]=y,nxt[tot]=head[x];head[x]=tot,c[tot]=z;}
void dfs1(int v){
int maxn=0;pt[v]=siz[v]=1;
for(int i=head[v];i;i=nxt[i]){
int y=vis[i];
if(pt[y]) continue;
a[y]=c[i];
fa[y]=v,dep[y]=dep[v]+1;
dfs1(y);
siz[v]+=siz[y];
if(siz[y]>maxn) {maxn=siz[y],hson[v]=y;}
}
}
void dfs2(int v){
dfn[v]=++cnt,id[cnt]=v;
if(!hson[v]) return;
top[hson[v]]=top[v];
dfs2(hson[v]);
for(int i=head[v];i;i=nxt[i]){
if(top[vis[i]]) continue;
top[vis[i]]=vis[i];
dfs2(vis[i]);
}
}
struct segtree{int l,r,maxx,add,cov;}tr[N<<2];
inline void pushcov(int k,int v) {tr[k].maxx=v,tr[k].cov=v,tr[k].add=0;}
inline void pushadd(int k,int v) {tr[k].maxx+=v,tr[k].add+=v;}
void pushdown(int k){
if(~tr[k].cov) pushcov(k<<1,tr[k].cov),pushcov(k<<1|1,tr[k].cov),tr[k].cov=-1;
if(tr[k].add) pushadd(k<<1,tr[k].add),pushadd(k<<1|1,tr[k].add),tr[k].add=0;
}
void build(int k,int l,int r){
tr[k].l=l,tr[k].r=r,tr[k].cov=-1;
if(l==r){tr[k].maxx=a[id[l]];return;}
build(k<<1,l,mid),build(k<<1|1,mid+1,r);
tr[k].maxx=max(tr[k<<1].maxx,tr[k<<1|1].maxx);
}
void update1(int k,int ql,int qr,int v){ //add
if(ql>rs || qr<ls) return;
if(ql<=ls && qr>=rs) return pushadd(k,v);
pushdown(k);
if(qr<=mid) update1(k<<1,ql,qr,v);
else if(ql>mid) update1(k<<1|1,ql,qr,v);
else update1(k<<1,ql,mid,v),update1(k<<1|1,mid+1,qr,v);
tr[k].maxx=max(tr[k<<1].maxx,tr[k<<1|1].maxx);
}
void update2(int k,int ql,int qr,int v){ //cov
if(ql>rs || qr<ls) return;
if(ql<=ls && qr>=rs) return pushcov(k,v);
pushdown(k);
if(qr<=mid) update2(k<<1,ql,qr,v);
else if(ql>mid) update2(k<<1|1,ql,qr,v);
else update2(k<<1,ql,mid,v),update2(k<<1|1,mid+1,qr,v);
tr[k].maxx=max(tr[k<<1].maxx,tr[k<<1|1].maxx);
}
int query(int k,int ql,int qr){
if(ql>rs || qr<ls) return 0;
if(ql<=ls && qr>=rs) return tr[k].maxx;
pushdown(k);
if(qr<=mid) return query(k<<1,ql,qr);
else if(ql>mid) return query(k<<1|1,ql,qr);
return max(query(k<<1,ql,mid),query(k<<1|1,mid+1,qr));
}
void change1(int x,int y,int v){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
update1(1,dfn[top[x]],dfn[x],v),x=fa[top[x]];
}
if(dep[x]<dep[y]) swap(x,y);
update1(1,dfn[y]+1,dfn[x],v);
}
void change2(int x,int y,int v){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
update2(1,dfn[top[x]],dfn[x],v),x=fa[top[x]];
}
if(dep[x]<dep[y]) swap(x,y);
update2(1,dfn[y]+1,dfn[x],v);
}
int ask(int x,int y){
int ans=0;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
ans=max(ans,query(1,dfn[top[x]],dfn[x])),x=fa[top[x]];
}
if(dep[x]<dep[y]) swap(x,y);
return max(ans,query(1,dfn[y]+1,dfn[x]));
}
int main(){
int n;
cin>>n;
for(int i=1;i<n;i++){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);add(y,x,z);
}
dfs1(1),top[1]=1;dfs2(1);build(1,1,n);
char op[10];
while(true){
scanf("%s",op);
if(op[0]=='S') break;
int x,y;
scanf("%d%d",&x,&y);
if(op[0]=='A') {int z;scanf("%d",&z);change1(x,y,z);}
else if(op[0]=='M') printf("%d\n",ask(x,y));
else{
if(op[1]=='o') {int z;scanf("%d",&z);change2(x,y,z);}
else{
int u=vis[x*2],v=vis[x*2-1];
if(dep[u]>dep[v])swap(u,v);
update2 (1,dfn[v],dfn[v],y);
}
}
}
return 0;
}