基准时间限制:3 秒 空间限制:524288 KB 分值: 80
难度:5级算法题
n个点被n-1条边连接成了一颗树,给出a~b和c~d两个区间,表示点的标号请你求出两个区间内各选一点之间的最大距离,即你需要求出max{dis(i,j) |a<=i<=b,c<=j<=d}
(PS 建议使用读入优化)
Input
第一行一个数字 n n<=100000。 第二行到第n行每行三个数字描述路的情况, x,y,z (1<=x,y<=n,1<=z<=10000)表示x和y之间有一条长度为z的路。 第n+1行一个数字m,表示询问次数 m<=100000。 接下来m行,每行四个数a,b,c,d。
Output
共m行,表示每次询问的最远距离
Input示例
5 1 2 1 2 3 2 1 4 3 4 5 4 1 2 3 4 5
Output示例
10
xfause
(题目提供者)
这题需要一个结论
设集合A中的最远点对为u,v
集合B中的最远点对为p,q
那么集合 A并B 的最远点对为u,v,p,q中的两个(即C(4,2)==6)
证明类似树的直径的证明
然后用欧拉序RMQ求lca+线段树+暴力合并就可以过这道题了
我rank16!!!
注意询问时只有4种情况(没有(u,v)和(p,q))(pushup和pushup_ans的区别)
其实我的代码加个函数可以简洁很多的
但是直接复制过来也不错QAQ
——————————分割线———————————————
突然发现我的lca写错了QAQ
应该是欧拉序中深度最小的点
而不是编号最小的。。。。。。
然而我竟然A了。。。。。
代码我懒得改了
大家自己注意啊QAQ
#include<cstdio>
#include<cstring>
inline int read()
{
int ans=0,f=1;char t=getchar();
while(t<'0'||t>'9') f=(t=='-'?-1:1),t=getchar();
while(t>='0'&&t<='9') ans=ans*10+t-'0',t=getchar();
return ans*f;
}
const int N=1e5+7;
struct node
{
int to,next,c;
}e[N<<1];
int first[N];int cnt;
inline void insert(int u,int v,int c)
{
e[++cnt]=(node){v,first[u],c};first[u]=cnt;
e[++cnt]=(node){u,first[v],c};first[v]=cnt;
}
int qu[N*2],visit[N];
int tar[N];
int dis[N];
void dfs(int x)
{
qu[++cnt]=x;tar[x]=cnt;visit[x]=1;
for(int k=first[x];k;k=e[k].next)
if(!visit[e[k].to])
{
dis[e[k].to]=dis[x]+e[k].c;
dfs(e[k].to);
qu[++cnt]=x;
}
}
int lg[N*2+8];
int f[N*2+8][25];
struct edgt
{
int l,r;int u,v;
int dis;
}tr[N*4];
#define lson ro<<1
#define rson ro<<1|1
const int inf=2*1e9+7;
inline int min(int u,int v)
{
return u<v?u:v;
}
inline void swap(int &a,int &b)
{
int tmp=a;
a=b,b=tmp;
}
inline int lca(int l,int r)
{
l=tar[l],r=tar[r];
if(l>r) swap(l,r);
int t=lg[r-l+1];
return min(f[l][t],f[r-(1<<t)+1][t]);
}
inline int querydis(int u,int v)
{
return dis[u]+dis[v]-(dis[lca(u,v)]<<1);
}
inline void pushup_ans(edgt &ro,edgt l,edgt r)
{
bool tag1=( (l.l==l.r) &&l.l>0),tag2=( (r.l==r.r) && (r.l>0) );
if(tag1&&!tag2)
{
int ans=0,i=0,j=0,tt=0;
tt=querydis(l.u,r.u);
if(tt>ans) ans=tt,i=l.u,j=r.u;
tt=querydis(l.u,r.v);
if(tt>ans) ans=tt,i=l.u,j=r.v;
ro.dis=ans,ro.u=i,ro.v=j;
}
else if(!tag1&&tag2)
{
int ans=0,i=0,j=0,tt=0;
tt=querydis(l.u,r.u);
if(tt>ans) ans=tt,i=l.u,j=r.u;
tt=querydis(l.v,r.u);
if(tt>ans) ans=tt,i=l.v,j=r.u;
ro.dis=ans,ro.u=i,ro.v=j;
}
else if(tag1&&tag2)
{
ro.u=l.l;ro.v=r.l;
ro.dis=querydis(ro.u,ro.v);
}
else
{
int ans=0,i=0,j=0,tt=0;
tt=querydis(l.u,r.u);
if(tt>ans) ans=tt,i=l.u,j=r.u;
tt=querydis(l.u,r.v);
if(tt>ans) ans=tt,i=l.u,j=r.v;
tt=querydis(l.v,r.u);
if(tt>ans) ans=tt,i=l.v,j=r.u;
tt=querydis(l.v,r.v);
if(tt>ans) ans=tt,i=l.v,j=r.v;
ro.dis=ans,ro.u=i,ro.v=j;
}
}
inline void pushup(edgt &ro,edgt l,edgt r)
{
bool tag1=( (l.l==l.r) &&l.l>0),tag2=( (r.l==r.r) && (r.l>0) );
if(tag1&&!tag2)
{
int ans=0,i=0,j=0,tt=0;
if(r.dis>ans) ans=r.dis,i=r.u,j=r.v;
tt=querydis(l.u,r.u);
if(tt>ans) ans=tt,i=l.u,j=r.u;
tt=querydis(l.u,r.v);
if(tt>ans) ans=tt,i=l.u,j=r.v;
ro.dis=ans,ro.u=i,ro.v=j;
}
else if(!tag1&&tag2)
{
int ans=0,i=0,j=0,tt=0;
if(l.dis>ans) ans=l.dis,i=l.u,j=l.v;
tt=querydis(l.u,r.u);
if(tt>ans) ans=tt,i=l.u,j=r.u;
tt=querydis(l.v,r.u);
if(tt>ans) ans=tt,i=l.v,j=r.u;
ro.dis=ans,ro.u=i,ro.v=j;
}
else if(tag1&&tag2)
{
ro.u=l.l;ro.v=r.l;
ro.dis=querydis(ro.u,ro.v);
}
else
{
int ans=0,i=0,j=0,tt=0;
if(l.dis>ans) ans=l.dis,i=l.u,j=l.v;
if(r.dis>ans) ans=r.dis,i=r.u,j=r.v;
tt=querydis(l.u,r.u);
if(tt>ans) ans=tt,i=l.u,j=r.u;
tt=querydis(l.u,r.v);
if(tt>ans) ans=tt,i=l.u,j=r.v;
tt=querydis(l.v,r.u);
if(tt>ans) ans=tt,i=l.v,j=r.u;
tt=querydis(l.v,r.v);
if(tt>ans) ans=tt,i=l.v,j=r.v;
ro.dis=ans,ro.u=i,ro.v=j;
}
}
void build(int ro,int l,int r)
{
tr[ro].l=l,tr[ro].r=r;
if(l==r)
{
tr[ro].u=l,tr[ro].v=l;
tr[ro].dis=-inf;
return;
}
int mid=(l+r)>>1;
build(lson,l,mid);build(rson,mid+1,r);
pushup(tr[ro],tr[lson],tr[rson]);
}
edgt query(int ro,int l,int r)
{
if(l<=tr[ro].l&&tr[ro].r<=r) return tr[ro];
int mid=(tr[ro].l+tr[ro].r)>>1;
if(r<=mid) return query(lson,l,r);
else if(l>mid) return query(rson,l,r);
else
{
edgt ans;
edgt a=query(lson,l,mid),b=query(rson,mid+1,r);
pushup(ans,a,b);
return ans;
}
}
int main()
{
int n=read();
int u,v,c;
for(int i=1;i<n;i++) u=read(),v=read(),c=read(),insert(u,v,c);
cnt=0;
dfs(1);
lg[1]=0;
for(int i=2;i<=cnt;i++) lg[i]=lg[i>>1]+1;
for(int i=1;i<=cnt;i++) f[i][0]=qu[i];
for(int j=1;j<=22;j++)
for(int i=1;i<=cnt-( 1<<(j -1) );i++)
f[i][j]=min(f[i][j-1],f[ i+( 1<< (j-1) )][ j-1 ]);
int p,q;
build(1,1,n);
int m;
m=read();
for(int i=1;i<=m;i++)
{
u=read(),v=read(),p=read(),q=read();
edgt a=query(1,u,v);
edgt b=query(1,p,q);
edgt ans;
pushup_ans(ans,a,b);
printf("%d\n",ans.dis);
}
return 0;
}