线段树套LCA。。。写了近200行
对于区间[a,b]和区间[c,d]上各选一点的最大长度,必定等于区间[a,b]内最远点对中的某一点,与区间[c,d]内最远点对中的某一点,这两点的距离。因为有这个性质,就可以在线段树上进行查询了。注意线段树中的合并merge操作,与求答案时的merge操作,有些不同。
#include <bits/stdc++.h>
using namespace std;
void read(int&a){
char ch;while(!((ch=getchar())>='0')&&(ch<='9'));
a=ch-'0';while(((ch=getchar())>='0')&&(ch<='9'))a*=10,a+=ch-'0';
}
inline void prin_d(long long x)
{
if (x > 9)
{
prin_d(x / 10);
}
putchar(x % 10 + '0');
return ;
}
const int MAXN=100100;
int node[MAXN<<1],first[MAXN],p[MAXN],dep[MAXN<<1];
long long dis[MAXN];
int dp[MAXN<<1][25];
struct Edge
{
int x,d;
};
vector <Edge> eg[MAXN];
void dfs(int &index,int u,int d,int par)
{
index++;
node[index]=u;
dep[index]=d;
first[u]=index;
for(int i=0;i<eg[u].size();i++)
{
if(eg[u][i].x==par) continue;
dfs(index,eg[u][i].x,d+1,u);
index++;
node[index]=u;
dep[index]=d;
}
}
void ST(int n)
{
int i,j,k=(int)(log((double)n)/log(2.0));
for(i=1;i<=n;i++)
dp[i][0]=i;
for(j=1;j<=k;j++)
{
for(i=1;i<=n-(1<<j)+1;i++)
{
int a=dp[i][j-1];
int b=dp[i+(1<<(j-1))][j-1];
if(dep[a]<dep[b])
dp[i][j]=a;
else
dp[i][j]=b;
}
}
}
int RMQ(int x,int y)
{
int k=(int)(log((double)(y-x+1))/log(2.0));
int a=dp[x][k];
int b=dp[y-(1<<k)+1][k];
if(dep[a]<dep[b])
return a;
else
return b;
}
int LCA(int u,int v)
{
int x=first[u],y=first[v];
if(x>y) swap(x,y);
int temp=RMQ(x,y);
return node[temp];
}
void dfsdis(int x,int par)
{
for(int i=0;i<eg[x].size();i++)
{
if(eg[x][i].x==par)
continue;
dis[eg[x][i].x]=dis[x]+eg[x][i].d;
dfsdis(eg[x][i].x,x);
}
}
long long pathdis(int u,int v)
{
return dis[u]+dis[v]-(dis[LCA(u,v)]<<1);
}
struct node
{
int l,r;
pair<int,int> pai;
}segtree[MAXN<<2];
pair<int,int> merge(const pair<int,int> &p1,const pair<int,int> &p2,bool flag)
{
long long dis1=pathdis(p1.first,p2.first),
dis2=pathdis(p1.first,p2.second),
dis3=pathdis(p1.second,p2.first),
dis4=pathdis(p1.second,p2.second),
dis5=pathdis(p1.first,p1.second),
dis6=pathdis(p2.first,p2.second);
if(flag)
{
if(dis5>=dis1&&dis5>=dis2&&dis5>=dis3&&dis5>=dis4&&dis5>=dis6)
return make_pair(p1.first,p1.second);
if(dis6>=dis1&&dis6>=dis2&&dis6>=dis3&&dis6>=dis4&&dis6>=dis5)
return make_pair(p2.first,p2.second);
}
if(dis1>=dis2&&dis1>=dis3&&dis1>=dis4) return make_pair(p1.first,p2.first);
if(dis2>=dis1&&dis2>=dis3&&dis2>=dis4) return make_pair(p1.first,p2.second);
if(dis3>=dis1&&dis3>=dis2&&dis3>=dis4) return make_pair(p1.second,p2.first);
if(dis4>=dis1&&dis4>=dis2&&dis4>=dis3) return make_pair(p1.second,p2.second);
}
void build(int i,int l,int r)
{
segtree[i].l=l;
segtree[i].r=r;
if(l==r)
{
segtree[i].pai.first=segtree[i].pai.second=l;
return;
}
int mid=(l+r)>>1;
build(i<<1,l,mid);
build(i<<1|1,mid+1,r);
segtree[i].pai=merge(segtree[i<<1].pai,segtree[i<<1|1].pai,1);
}
pair<int,int> query(int i,int a,int b)
{
if(segtree[i].l==a&&segtree[i].r==b)
{
return segtree[i].pai;
}
int mid=(segtree[i].l+segtree[i].r)>>1;
if(b<=mid)
return query(i<<1,a,b);
else if(a>mid)
return query(i<<1|1,a,b);
else
return merge(query(i<<1,a,mid),query(i<<1|1,mid+1,b),1);
}
int main()
{
int n,u,v,siz,i,q,a,b,c,d;
Edge etmp;
pair<int,int> ans;
while(~scanf("%d",&n))
{
for(i=1;i<=n;i++)
eg[i].clear();
for(i=1;i<n;i++)
{
read(u); read(v); read(etmp.d);
etmp.x=u;
eg[v].push_back(etmp);
etmp.x=v;
eg[u].push_back(etmp);
}
siz=0;
dfs(siz,1,1,-1);
ST(siz);
dis[1]=0;
dfsdis(1,-1);
build(1,1,n);
read(q);
while(q--)
{
read(a); read(b); read(c); read(d);
ans=merge(query(1,a,b),query(1,c,d),0);
prin_d(pathdis(ans.first,ans.second));
puts("");
}
}
return 0;
}