题解:P9058 [Ynoi2004] rpmtdq
树上路径,考虑点分治。对于当前根
对于在
于是我们有若干点对
对于一个支配点对
如果
正反分别做单调栈维护,每个点贡献
扫描线,二维数点即可。时间复杂度
#include<bits/stdc++.h>
#define int long long
#define rd read()
#define gc pa == pb && (pb = (pa = buf) + fread(buf, 1, 100000, stdin), pa == pb) ? EOF : *pa++
using namespace std;
static char buf[100000], * pa(buf), * pb(buf);
inline int read()
{
register int x=0,s=gc;
while(!isdigit(s))s=gc;
while(isdigit(s))x=(x<<1)+(x<<3)+(s^48),s=gc;
return x;
}
const int N=200005,M=1000005,inf=1e16;
bool vis[N];
int n,m,rt,sz,mx[N],siz[N],ans[M];
vector<pair<int,int> > v[N],q[N],p[N],d;
inline void chkmax(int &x,int y){x=(x<y?y:x);}
inline void chkmin(int &x,int y){x=(x>y?y:x);}
inline void find(int x,int f)
{
siz[x]=1,mx[x]=0;
for(auto [i,j]:v[x])
if(i!=f&&!vis[i])find(i,x),siz[x]+=siz[i],chkmax(mx[x],siz[i]);
chkmax(mx[x],sz-siz[x]);
if(mx[x]<mx[rt])rt=x;
}
inline void get(int x,int l,int f)
{
if(vis[x])return;
d.push_back({x,l});
for(auto [i,j]:v[x])if(i!=f)get(i,l+j,x);
}
inline void sol(int x)
{
if(vis[x])return;
vis[x]=1;
for(auto [i,j]:v[x])get(i,j,x);
d.push_back({x,0}),sort(d.begin(),d.end());
stack<pair<int,int> > st;
for(auto [i,j]:d)
{
while(st.size()&&st.top().second>j)st.pop();
if(st.size())p[i].push_back({st.top().first,st.top().second+j});
st.push({i,j});
}
while(st.size())st.pop();
reverse(d.begin(),d.end());
for(auto [i,j]:d)
{
while(st.size()&&st.top().second>j)st.pop();
if(st.size())p[st.top().first].push_back({i,st.top().second+j});
st.push({i,j});
}
d.clear();
for(auto [i,j]:v[x])if(!vis[i])rt=0,sz=siz[i],find(i,x),sol(rt);
}
struct BIT
{
int c[N];
inline void chk(int x,int y){while(x)chkmin(c[x],y),x^=(x&-x);}
inline int ask(int x){int s=LONG_LONG_MAX;while(x<=n)chkmin(s,c[x]),x+=(x&-x);return s;}
}G;
signed main()
{
n=rd;for(int i=1,x,y,w;i<n;v[x].push_back({y,w}),v[y].push_back({x,w}),++i)x=rd,y=rd,w=rd;
m=rd;for(int i=1,l;i<=m;++i)l=rd,q[rd].push_back({l,i});
mx[0]=n+1,rt=0,sz=n,find(1,0),sol(rt),memset(G.c,0x3f,sizeof(G.c));
for(int i=1;i<=n;++i)
{
for(auto [l,k]:p[i])G.chk(l,k);
for(auto [l,id]:q[i])ans[id]=G.ask(l);
}
for(int i=1;i<=m;++i)cout<<(ans[i]>inf?-1:ans[i])<<'\n';
return 0;
}