洛谷 P4315 月下“毛景樹”
阿新 • • 發佈:2020-10-20
洛谷 P4315 月下“毛景樹”
題目描述
毛毛蟲經過及時的變形,最終逃過的一劫,離開了菜媽的菜園。 毛毛蟲經過千山萬水,歷盡千辛萬苦,最後來到了小小的紹興一中的校園裡。
爬啊爬~爬啊爬毛毛蟲爬到了一顆小小的“毛景樹”下面,發現樹上長著他最愛吃的毛毛果~ “毛景樹”上有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”結束。
輸出格式
對於毛毛蟲的每個詢問操作,輸出一個答案。
題解:
邊轉點是這道題唯一可以稱得上難點的點。
然後就是裸的樹剖架線段樹。
程式碼:
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> using namespace std; const int N = 100100; int ls(int x) {return x << 1;} int rs(int x) {return x << 1 | 1;} int n , cnt; int u[N] , v[N] , w[N] , dep[N] , size[N] , fa[N] , top[N] , hs[N] , a[N] , son[N] , head[N] , dfn[N] , id[N]; int maxn[N << 2] , tag[N << 2] , lazy[N << 2]; char s[10]; struct Edge { int to , dis , nxt; }e[N << 1]; void add(int from,int to,int dis) { e[++cnt] = (Edge){to,dis,head[from]}; head[from] = cnt; } void get_tree(int now) { size[now] = 1; for(int i = head[now];i;i = e[i].nxt) { int to = e[i].to; if(dep[to]) continue; a[to] = e[i].dis; dep[to] = dep[now] + 1; fa[to] = now; get_tree(to); size[now] += size[to]; if(size[to] > size[hs[now]]) hs[now] = to; } } void dfs(int now,int topfa) { dfn[now] = ++cnt; id[cnt] = now; top[now] = topfa; if(hs[now]) dfs(hs[now],topfa); for(int i = head[now];i;i = e[i].nxt) { int to = e[i].to; if(to == fa[now] || to == hs[now]) continue; dfs(to,to); } } void build(int p,int l,int r) { if(l == r) { maxn[p] = a[id[l]]; return ; } int mid = (l + r) >> 1; build(ls(p),l,mid); build(rs(p),mid+1,r); maxn[p] = max(maxn[ls(p)],maxn[rs(p)]); } void push_down(int p,int l,int r) { if(lazy[p] >= 0) { tag[ls(p)] = tag[rs(p)] = 0; maxn[ls(p)] = maxn[rs(p)] = lazy[ls(p)] = lazy[rs(p)] = lazy[p]; lazy[p] = -1; } if(tag[p]) { tag[ls(p)] += tag[p]; tag[rs(p)] += tag[p]; maxn[ls(p)] += tag[p]; maxn[rs(p)] += tag[p]; tag[p] = 0; } } int query_max(int p,int l,int r,int x,int y) { if(x <= l && r <= y) return maxn[p]; int mid = (l + r) >> 1 , res = 0; push_down(p,l,r); if(x <= mid) res = max(res,query_max(ls(p),l,mid,x,y)); if(y > mid) res = max(res,query_max(rs(p),mid+1,r,x,y)); return res; } int sec_max(int x,int y) { int res = 0; while(top[x] != top[y]) { if(dep[top[x]] < dep[top[y]]) swap(x,y); res = max(res , query_max(1,1,n,dfn[top[x]],dfn[x])); x = fa[top[x]]; } if(dep[x] < dep[y]) swap(x,y); if(dfn[y] < dfn[x]) res = max(res,query_max(1,1,n,dfn[y]+1,dfn[x])); return res; } void chenge_add(int p,int l,int r,int x,int y,int k) { if(x <= l && r <= y) { tag[p] += k; maxn[p] += k; return ; } int mid = (l + r) >> 1; push_down(p,l,r); if(x <= mid) chenge_add(ls(p),l,mid,x,y,k); if(y > mid) chenge_add(rs(p),mid+1,r,x,y,k); maxn[p] = max(maxn[ls(p)],maxn[rs(p)]); } void sec_add(int x,int y,int z) { while(top[x] != top[y]) { if(dep[top[x]] < dep[top[y]]) swap(x,y); chenge_add(1,1,n,dfn[top[x]],dfn[x],z); x = fa[top[x]]; } if(dep[x] < dep[y]) swap(x,y); if(dfn[y] < dfn[x]) chenge_add(1,1,n,dfn[y]+1,dfn[x],z); } void chenge_cover(int p,int l,int r,int x,int y,int k) { if(x <= l && r <= y) { maxn[p] = k; tag[p] = 0; lazy[p] = k; return ; } int mid = (l + r) >> 1; push_down(p,l,r); if(x <= mid) chenge_cover(ls(p),l,mid,x,y,k); if(y > mid) chenge_cover(rs(p),mid+1,r,x,y,k); maxn[p] = max(maxn[ls(p)],maxn[rs(p)]); } void sec_cover(int x,int y,int z) { while(top[x] != top[y]) { if(dep[top[x]] < dep[top[y]]) swap(x,y); chenge_cover(1,1,n,dfn[top[x]],dfn[x],z); x = fa[top[x]]; } if(dep[x] < dep[y]) swap(x,y); if(dfn[y] < dfn[x]) chenge_cover(1,1,n,dfn[y]+1,dfn[x],z); } void chenge_(int p,int l,int r,int x,int k) { if(l == r) { maxn[p] = k; tag[p] = 0; lazy[p] = k; return ; } int mid = (l + r) >> 1; push_down(p,l,r); if(x <= mid) chenge_(ls(p),l,mid,x,k); else chenge_(rs(p),mid+1,r,x,k); maxn[p] = max(maxn[ls(p)],maxn[rs(p)]); } int main() { memset(lazy,-1,sizeof lazy); scanf("%d",&n); for(int i = 1;i < n;i ++) { scanf("%d%d%d",&u[i],&v[i],&w[i]); add(u[i],v[i],w[i]); add(v[i],u[i],w[i]); } cnt = 0; dep[1] = 1; get_tree(1); dfs(1,1); build(1,1,n); for(int i = 1;i < n;i ++) { if(fa[u[i]] == v[i]) son[i] = u[i]; else son[i] = v[i]; } while(1) { int x , y , z; scanf("%s",s); if(s[0] == 'S') break; if(s[0] == 'M') { scanf("%d%d",&x,&y); printf("%d\n",sec_max(x,y)); } else if(s[0] == 'A') { scanf("%d%d%d",&x,&y,&z); sec_add(x,y,z); } else if(s[1] == 'o') { scanf("%d%d%d",&x,&y,&z); sec_cover(x,y,z); } else { scanf("%d%d",&x,&y); chenge_(1,1,n,dfn[son[x]],y); } } return 0; }