题解:由于区间内每个点和(x)的lca都不尽相同,我们很难用(dep_x+dep_y-2 imes dep_{lca})来进行求解。于是考虑点分治,把询问离线下来,挂在点(x)上。
发现问题变得很简单:我们只需要扫一遍分治中心的所有儿子,先在线段树上查一下区间离它最远的点的距离,然后再把自己加进线段树里就行了,注意正反要各做一遍。由于每个点只会涉及到log次线段树的单点修改、区间查询,时间复杂度就是(O(nlog^2n))。
如果本题强制在线,那么只需要把所有分治中心的线段树(或者平衡树)都建出来,然后在点分树上跳father,注意查的时候要减去它所在子树在线段树上的贡献就行了,这个东西对于做过动态点分治的大神们应该不陌生。
时间复杂度:(O(nlog^2n))。
代码:
#include<bits/stdc++.h>
using namespace std;
#define re register int
#define F(x,y,z) for(re x=y;x<=z;x++)
#define FOR(x,y,z) for(re x=y;x>=z;x--)
typedef long long ll;
#define I inline void
#define IN inline int
#define C(x,y) memset(x,y,sizeof(x))
#define STS system("pause")
template<class D>I read(D &res){
res=0;register D g=1;register char ch=getchar();
while(!isdigit(ch)){
if(ch=='-')g=-1;
ch=getchar();
}
while(isdigit(ch)){
res=(res<<3)+(res<<1)+(ch^48);
ch=getchar();
}
res*=g;
}
const int INF=1e9+7;
struct E{
int to,nt,w;
}e[202000];
struct P{
int x,y,id;
P(int _x=0,int _y=0,int _id=0){x=_x;y=_y;id=_id;}
};
#define T e[k].to
int n,m,rot,head[101000],tot,vis[101000],siz[101000],mx[101000],N,maxi,root,ans[101000];
vector<int>G[101000],tmp;
vector<P>t[101000];
struct Segtree{
int tr[404000],laz[404000];
#define all 1,1,n
#define lt k<<1,l,mid
#define rt k<<1|1,mid+1,r
I add(int k){tr[k]=INF;laz[k]=1;}
I push_down(int k){
add(k<<1),add(k<<1|1);laz[k]=0;
}
I modi(int k,int l,int r,int x,int w){
if(l==r)return tr[k]=w,void();
if(laz[k])push_down(k);
re mid=(l+r)>>1;
if(x<=mid)modi(lt,x,w);
else modi(rt,x,w);
tr[k]=min(tr[k<<1],tr[k<<1|1]);
}
IN ques(int k,int l,int r,int x,int y){
if(x>r||y<l)return INF;
if(x<=l&&r<=y)return tr[k];
if(laz[k])push_down(k);
re mid=(l+r)>>1;
return min(ques(lt,x,y),ques(rt,x,y));
}
}S;
I add(int x,int y,int w){
e[++tot].to=y;e[tot].nt=head[x];head[x]=tot;e[tot].w=w;
}
I findroot(int x,int fa){
siz[x]=1;mx[x]=0;
for(re k=head[x];k!=-1;k=e[k].nt){
if(T==fa||vis[T])continue;
findroot(T,x);mx[x]=max(mx[x],siz[T]);
siz[x]+=siz[T];
}
mx[x]=max(mx[x],N-siz[x]);
if(mx[x]<maxi)maxi=mx[x],root=x;
}
I D_1(int x,int fa){
siz[x]=1;
for(re k=head[x];k!=-1;k=e[k].nt){
if(T==fa||vis[T])continue;
D_1(T,x);siz[x]+=siz[T];
}
}
I divided(int x,int fa){
if(fa)G[fa].emplace_back(x);
D_1(x,0);vis[x]=1;
for(re k=head[x];k!=-1;k=e[k].nt){
if(T==fa||vis[T])continue;
N=siz[T];maxi=INF;
findroot(T,x);divided(root,x);
}
}
I D_2(int x,int fa,int dist){
for(auto d:t[x])ans[d.id]=min(ans[d.id],S.ques(all,d.x,d.y)+dist);
for(re k=head[x];k!=-1;k=e[k].nt){
if(T==fa||vis[T])continue;
D_2(T,x,dist+e[k].w);
}
}
I D_3(int x,int fa,int dist){
S.modi(all,x,dist);
for(re k=head[x];k!=-1;k=e[k].nt){
if(T==fa||vis[T])continue;
D_3(T,x,dist+e[k].w);
}
}
I solve(int x){
S.add(1);S.modi(all,x,0);tmp.clear();
for(re k=head[x];k!=-1;k=e[k].nt){
if(vis[T])continue;
tmp.emplace_back(k);
D_2(T,x,e[k].w);D_3(T,x,e[k].w);
}
reverse(tmp.begin(),tmp.end());
S.add(1);S.modi(all,x,0);
for(auto k:tmp)D_2(T,x,e[k].w),D_3(T,x,e[k].w);
for(auto d:t[x])ans[d.id]=min(ans[d.id],S.ques(all,d.x,d.y));
vis[x]=1;
for(auto d:G[x])solve(d);
}
int main(){
read(n);C(head,-1);tot=-1;
re X,Y,W;
F(i,1,n-1){
read(X);read(Y);read(W);
add(X,Y,W);add(Y,X,W);
}
N=n;maxi=INF;findroot(1,0);rot=root;divided(root,0);
read(m);
F(i,1,m){
read(X);read(Y);read(W);
t[W].emplace_back(P(X,Y,i));ans[i]=INF;
}
C(vis,0);solve(rot);
F(i,1,m)printf("%d
",ans[i]);
return 0;
}