Vulnstack紅隊(一)
阿新 • • 發佈:2022-04-02
P4374 [USACO18OPEN]Disruption P
分析
還是蠻套路的,我們來總結一下這題的推理過程
首先考慮,從每一條邊去找哪一條邊是我們需要的最短的替換路。發現太麻煩了,則正難則反,我們從新加的每一條路去考慮。
對於新加的邊,其能更新其兩個端點在樹中的路徑
依據此,我們的問題即轉化為了,如何快速的對樹中路徑中的可以替換的最小值進行更新
嗷,還有一個小問題,邊權化點權,可以在這裡看到操作方法P4114 Qtree1
不難想到利用線段樹+樹剖
問題就結束了,時間複雜度為\(O(nlog^2n)\)
但這依舊不是最優寫法,我們可以考慮並查集(最近碰到好幾道並查集的,滋,明天看看能不能全部理解一下,欠)
AC_code
#include<bits/stdc++.h> using namespace std; const int N = 5e4 + 10,INF = 0x3f3f3f3f; struct Node { int l,r,mi; }tr[N<<2]; int h[N],e[N<<1],ne[N<<1],idx; int sz[N],dep[N],fa[N],son[N]; int top[N],id[N],ts; int n,m; void add(int a,int b) { e[idx] = b,ne[idx] = h[a],h[a] = idx++; } void dfs1(int u,int pa,int depth) { sz[u] = 1,dep[u] = depth,fa[u] = pa; for(int i=h[u];~i;i=ne[i]) { int j = e[i]; if(j==pa) continue; dfs1(j,u,depth+1); if(sz[j]>sz[son[u]]) son[u] = j; sz[u] += sz[j]; } } void dfs2(int u,int tp) { top[u] = tp,id[u] = ++ts; if(!son[u]) return ; dfs2(son[u],tp); for(int i=h[u];~i;i=ne[i]) { int j = e[i]; if(j==fa[u]||j==son[u]) continue; dfs2(j,j); } } void pushdown(int u) { auto &root = tr[u],&left = tr[u<<1],&right = tr[u<<1|1]; if(root.mi!=INF) { left.mi = min(left.mi,root.mi); right.mi = min(right.mi,root.mi); root.mi = INF; } } void build(int u,int l,int r) { tr[u] = {l,r,INF}; if(l==r) return ; int mid = l + r >> 1; build(u<<1,l,mid),build(u<<1|1,mid+1,r); } void modify(int u,int l,int r,int k) { if(l<=tr[u].l&&tr[u].r<=r) { tr[u].mi = min(tr[u].mi,k); return ; } pushdown(u); int mid = tr[u].l + tr[u].r >> 1; if(l<=mid) modify(u<<1,l,r,k); if(r>mid) modify(u<<1|1,l,r,k); } int query(int u,int x) { if(tr[u].l==tr[u].r) return tr[u].mi; pushdown(u); int mid = tr[u].l + tr[u].r >> 1; if(x<=mid) return query(u<<1,x); else return query(u<<1|1,x); } int main() { scanf("%d%d",&n,&m); vector<pair<int,int>> edges; memset(h,-1,sizeof h); for(int i=0;i<n-1;i++) { int a,b;scanf("%d%d",&a,&b); edges.push_back({a,b}); add(a,b),add(b,a); } dfs1(1,-1,1); dfs2(1,1); build(1,1,n); while(m--) { int a,b,c; scanf("%d%d%d",&a,&b,&c); while(top[a]!=top[b]) { if(dep[top[a]]<dep[top[b]]) swap(a,b); modify(1,id[top[a]],id[a],c); a = fa[top[a]]; } if(a!=b) { if(dep[a]<dep[b]) swap(a,b); modify(1,id[b]+1,id[a],c); } } for(auto edge:edges) { int a = edge.first,b = edge.second; if(dep[a]<dep[b]) swap(a,b); int res = query(1,id[a]); if(res==INF) puts("-1"); else printf("%d\n",res); } return 0; }