题解:P11317 [RMI 2021] 路径 / Paths
Solution
奶龙题,但是为什么想了半个小时???
如果不换根,答案就是将树进行长链剖分后选前
考虑换根的过程中直接维护所有的长链。发现从
这个问题咋做都行,随便写了一个线段树。(显然可以也 multiset)
刚开始把子树内、子树外的长链分开考虑了,然后发现必须可持久化……
#include<bits/stdc++.h>
#define int long long
#define ffor(i,a,b) for(int i=(a);i<=(b);i++)
#define roff(i,a,b) for(int i=(a);i>=(b);i--)
using namespace std;
const int MAXN=4e5+10;
int n,k,mx_in[MAXN],mx_out[MAXN],lsh[MAXN],tot,ans[MAXN];
namespace DS {
int cnt[MAXN<<2],sum[MAXN<<2];
#define lson (k<<1)
#define rson (k<<1|1)
#define mid (l+r>>1)
void update(int k,int l,int r,int pos,int dcnt,int dsum) {
cnt[k]+=dcnt,sum[k]+=dsum;
if(l==r) return ;
if(pos<=mid) update(lson,l,mid,pos,dcnt,dsum);
else update(rson,mid+1,r,pos,dcnt,dsum);
return ;
}
int calc(int k,int l,int r,int c) {
if(c>=cnt[k]) return sum[k];
if(l==r) return lsh[l]*c;
if(c<=cnt[rson]) return calc(rson,mid+1,r,c);
return sum[rson]+calc(lson,l,mid,c-cnt[rson]);
}
};
vector<pair<int,int>> G[MAXN],T[MAXN];
void dfs1(int u,int f) {
for(auto pr:G[u]) {
int v=pr.first,w=pr.second;
if(v==f) continue ;
dfs1(v,u),mx_in[u]=max(mx_in[u],mx_in[v]+w),T[u].push_back(pr);
}
return ;
}
void dfs2(int u,int f) {
int mx=mx_out[u];
for(auto pr:T[u]) {
int v=pr.first,w=pr.second;
mx_out[v]=max(mx_out[v],mx+w),mx=max(mx,mx_in[v]+w);
}
reverse(T[u].begin(),T[u].end()),mx=mx_out[u];
for(auto pr:T[u]) {
int v=pr.first,w=pr.second;
mx_out[v]=max(mx_out[v],mx+w),mx=max(mx,mx_in[v]+w);
lsh[++tot]=mx_in[v]+w,lsh[++tot]=mx_out[v]-w,lsh[++tot]=mx_in[v],lsh[++tot]=mx_out[v];
}
for(auto pr:T[u]) dfs2(pr.first,u);
return ;
}
int find(int k) {return lower_bound(lsh+1,lsh+tot+1,k)-lsh;}
void dfs3(int u,int f) {
int flg=0;
for(auto pr:T[u]) {
int v=pr.first,w=pr.second;
if(mx_in[v]+w!=mx_in[u]||flg) DS::update(1,1,tot,find(mx_in[v]+w),1,mx_in[v]+w);
else flg=1;
}
for(auto pr:T[u]) dfs3(pr.first,u);
return ;
}
void dfs4(int u,int f) {
ans[u]=DS::calc(1,1,tot,k);
for(auto pr:T[u]) {
int v=pr.first,w=pr.second;
int del1=find(mx_in[v]+w),del2=find(mx_out[v]-w);
int add1=find(mx_in[v]),add2=find(mx_out[v]);
DS::update(1,1,tot,del1,-1,-(mx_in[v]+w));
DS::update(1,1,tot,del2,-1,-(mx_out[v]-w));
DS::update(1,1,tot,add1,1,mx_in[v]);
DS::update(1,1,tot,add2,1,mx_out[v]);
dfs4(v,u);
DS::update(1,1,tot,del1,1,mx_in[v]+w);
DS::update(1,1,tot,del2,1,mx_out[v]-w);
DS::update(1,1,tot,add1,-1,-mx_in[v]);
DS::update(1,1,tot,add2,-1,-mx_out[v]);
}
return ;
}
signed main() {
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin>>n>>k;
ffor(i,1,n-1) {int u,v,w;cin>>u>>v>>w,G[u].push_back({v,w}),G[v].push_back({u,w});}
dfs1(1,0),dfs2(1,0);
sort(lsh+1,lsh+tot+1),tot=unique(lsh+1,lsh+tot+1)-lsh-1;
DS::update(1,1,n,find(mx_in[1]),1,mx_in[1]),dfs3(1,0);
dfs4(1,0);
ffor(i,1,n) cout<<ans[i]<<'\n';
return 0;
}