有一个结论:两个区间的最长路的端点一定是这两个区间中的最长路端点(4选2),所以可以用线段树来维护区间最长路的两个端点,然后最终合并即可
1 #include2 using namespace std; 3 #define N 100005 4 #define L (k<<1) 5 #define R (L+1) 6 #define mid (l+r>>1) 7 struct ji{ 8 int nex,to,len; 9 }edge[N<<1]; 10 struct zj{ 11 int a[2]; 12 }tr[N<<2]; 13 int E,n,m,x1,y11,x2,y2,x,y,z,head[N],in[N],out[N],sh[N],f[N][21]; 14 void add(int x,int y,int z){ 15 edge[E].nex=head[x]; 16 edge[E].to=y; 17 edge[E].len=z; 18 head[x]=E++; 19 } 20 bool pd(int x,int y){ 21 return (in[x]<=in[y])&&(out[y]<=out[x]); 22 } 23 int lca(int x,int y){ 24 if (pd(x,y))return x; 25 for(int i=20;i>=0;i--) 26 if (!pd(f[x][i],y))x=f[x][i]; 27 return f[x][0]; 28 } 29 int dis(int x,int y){ 30 if ((!x)&&(!y))return -1; 31 if ((!x)||(!y))return 0; 32 return sh[x]+sh[y]-2*sh[lca(x,y)]; 33 } 34 void dfs(int k,int fa,int s){ 35 sh[k]=s; 36 in[k]=++x; 37 f[k][0]=fa; 38 for(int i=1;i<=20;i++)f[k][i]=f[f[k][i-1]][i-1]; 39 for(int i=head[k];i!=-1;i=edge[i].nex) 40 if (edge[i].to!=fa)dfs(edge[i].to,k,s+edge[i].len); 41 out[k]=++x; 42 } 43 zj merge(zj x,zj y){ 44 int ans=max(dis(x.a[0],x.a[1]),dis(y.a[0],y.a[1])); 45 for(int i=0;i<2;i++) 46 for(int j=0;j<2;j++)ans=max(ans,dis(x.a[i],y.a[j])); 47 if (dis(x.a[0],x.a[1])==ans)return x; 48 if (dis(y.a[0],y.a[1])==ans)return y; 49 for(int i=0;i<2;i++) 50 for(int j=0;j<2;j++) 51 if (dis(x.a[i],y.a[j])==ans)return zj{x.a[i],y.a[j]}; 52 } 53 void build(int k,int l,int r){ 54 if (l==r){ 55 tr[k]=zj{l,0}; 56 return; 57 } 58 build(L,l,mid); 59 build(R,mid+1,r); 60 tr[k]=merge(tr[L],tr[R]); 61 } 62 zj query(int k,int l,int r,int x,int y){ 63 if ((l>y)||(x>r))return zj{0,0}; 64 if ((x<=l)&&(r<=y))return tr[k]; 65 return merge(query(L,l,mid,x,y),query(R,mid+1,r,x,y)); 66 } 67 int main(){ 68 scanf("%d",&n); 69 memset(head,-1,sizeof(head)); 70 for(int i=1;i ){ 71 scanf("%d%d%d",&x,&y,&z); 72 add(x,y,z); 73 add(y,x,z); 74 } 75 x=0; 76 dfs(1,1,0); 77 build(1,1,n); 78 scanf("%d",&m); 79 for(int i=1;i<=m;i++){ 80 scanf("%d%d%d%d",&x1,&y11,&x2,&y2); 81 z=0; 82 zj o1=query(1,1,n,x1,y11),o2=query(1,1,n,x2,y2); 83 for(int x=0;x<2;x++) 84 for(int y=0;y<2;y++)z=max(z,dis(o1.a[x],o2.a[y])); 85 printf("%d\n",z); 86 } 87 }