luogu P4315 月下“毛景樹” 題解
阿新 • • 發佈:2020-10-07
前言
這大概是本蒟蒻A掉的題裡面碼量最大的一道題了。我自認為碼風比較緊湊,但還是寫了180行。
從下午2點多調到晚上8點。中間小錯不斷。最後還是藉助了郭神的AC程式碼。。
%%%stO郭神Orz%%%
還是我程式碼能力不夠。以後要多寫一些這樣的題練練手。
解析:
題目相當裸。樹鏈剖分+線段樹維護區間最大值。
需要注意的點大致如下:
1.邊權化點權
2.線段樹需要實現的功能:區間加,區間賦值,區間查詢最大值。
看起來貌似有手就行其實對於郭神這樣的神犇確實有手就行,但是本蒟蒻調了一下午。。。
犯的其實都是一些低錯,大概如下:
1.3個modify函式用串了
2.樹鏈剖分跳top的時候,注意是 \(dfn[top[u]]<=dfn[u]\)
modifyfz(1,1,n,dfn[top[u]],dfn[u],w);
而不是
modifyfz(1,1,n,dfn[u],dfn[top[u]],w);
3.注意在pushdown的時候要先判一下有沒有區間賦值標記。
真正因為有理解上的問題而犯的錯誤:
在區間修改時要下傳標記。每次更新前要保證該節點的狀態一定是最新的,否則就會出錯。
完整程式碼:
#include <bits/stdc++.h> using namespace std; const int maxn=100000+10; int n,cnt,Time; int head[maxn],tree[maxn<<2],lazyfz[maxn<<2],lazyadd[maxn<<2],top[maxn],fa[maxn],son[maxn],size[maxn],depth[maxn],dfn[maxn],w[maxn]; struct node{ int to,next,val; }edge[maxn<<1]; struct Node{ int from,to; }b[maxn]; void add(int from,int to,int val){ edge[++cnt].to=to; edge[cnt].val=val; edge[cnt].next=head[from]; head[from]=cnt; } void dfs1(int u,int f){ fa[u]=f; size[u]=1; for(int i=head[u];i;i=edge[i].next){ int v=edge[i].to; if(v==f) continue; depth[v]=depth[u]+1; dfs1(v,u); size[u]+=size[v]; if(size[v]>size[son[u]]) son[u]=v; } } void dfs2(int u,int t,int s){ top[u]=t; dfn[u]=++Time; w[Time]=s; if(son[u]){ for(int i=head[u];i;i=edge[i].next){ int v=edge[i].to; if(v==son[u]){ dfs2(v,t,edge[i].val); break; } } } for(int i=head[u];i;i=edge[i].next){ int v=edge[i].to; if(v==fa[u]||v==son[u]) continue; dfs2(v,v,edge[i].val); } } void build(int rt,int l,int r){ lazyfz[rt]=-1; if(l==r){ tree[rt]=w[l]; return; } int mid=(l+r)>>1; build(rt<<1,l,mid); build(rt<<1|1,mid+1,r); tree[rt]=max(tree[rt<<1],tree[rt<<1|1]); } void updatefz(int rt,int w){ tree[rt]=lazyfz[rt]=w; lazyadd[rt]=0; } void updateadd(int rt,int w){ tree[rt]+=w; lazyadd[rt]+=w; } void pushdown(int rt){ if(lazyfz[rt]!=-1){ updatefz(rt<<1,lazyfz[rt]); updatefz(rt<<1|1,lazyfz[rt]); lazyfz[rt]=-1; } if(lazyadd[rt]){ updateadd(rt<<1,lazyadd[rt]); updateadd(rt<<1|1,lazyadd[rt]); lazyadd[rt]=0; } } void modifyadd(int rt,int l,int r,int s,int t,int w){ if(s<=l&&r<=t){ updateadd(rt,w); return; } int mid=(l+r)>>1; pushdown(rt); if(s<=mid) modifyadd(rt<<1,l,mid,s,t,w); if(t>mid) modifyadd(rt<<1|1,mid+1,r,s,t,w); tree[rt]=max(tree[rt<<1],tree[rt<<1|1]); } void Modify(int u,int v,int w){ while(top[u]!=top[v]){ if(depth[top[u]]<depth[top[v]]) swap(u,v); modifyadd(1,1,n,dfn[top[u]],dfn[u],w); u=fa[top[u]]; } if(v==u) return; if(depth[u]>depth[v]) swap(u,v); modifyadd(1,1,n,dfn[u]+1,dfn[v],w); } void modifyfz(int rt,int l,int r,int s,int t,int w){ if(s<=l&&r<=t){ updatefz(rt,w); return; } int mid=(l+r)>>1; pushdown(rt); if(s<=mid) modifyfz(rt<<1,l,mid,s,t,w); if(t>mid) modifyfz(rt<<1|1,mid+1,r,s,t,w); tree[rt]=max(tree[rt<<1],tree[rt<<1|1]); } void Cover(int u,int v,int w){ while(top[u]!=top[v]){ if(depth[top[u]]<depth[top[v]]) swap(u,v); modifyfz(1,1,n,dfn[top[u]],dfn[u],w); u=fa[top[u]]; } if(v==u) return; if(depth[u]>depth[v]) swap(u,v); modifyfz(1,1,n,dfn[u]+1,dfn[v],w); } int query(int rt,int l,int r,int s,int t){ if(s<=l&&r<=t) return tree[rt]; int mid=(l+r)>>1; pushdown(rt); if(t<=mid) return query(rt<<1,l,mid,s,t); if(s>mid) return query(rt<<1|1,mid+1,r,s,t); else return max(query(rt<<1,l,mid,s,t),query(rt<<1|1,mid+1,r,s,t)); } int Query(int u,int v){ int res=-100000000; while(top[u]!=top[v]){ if(depth[top[u]]<depth[top[v]]) swap(u,v); res=max(res,query(1,1,n,dfn[top[u]],dfn[u])); u=fa[top[u]]; } if(u==v) return res; if(depth[u]>depth[v]) swap(u,v); res=max(res,query(1,1,n,dfn[u]+1,dfn[v])); return res; } void Solve(){ scanf("%d",&n); for(int i=1,x,y,z;i<n;++i){ scanf("%d%d%d",&x,&y,&z); b[i].from=x; b[i].to=y; add(x,y,z); add(y,x,z); } dfs1(1,0); dfs2(1,1,0); build(1,1,n); char ccc[10]; int x,y,z; while(1){ scanf("%s",ccc); if(ccc[0]=='S') return; if(ccc[0]=='C'){ if(ccc[1]=='h'){ scanf("%d%d",&x,&y); int d=max(dfn[b[x].from],dfn[b[x].to]); modifyfz(1,1,n,d,d,y); }else{ scanf("%d%d%d",&x,&y,&z); Cover(x,y,z); } }else if(ccc[0]=='A'){ scanf("%d%d%d",&x,&y,&z); Modify(x,y,z); }else{ scanf("%d%d",&x,&y); printf("%d\n",Query(x,y)); } } } int main(){ Solve(); return 0; }