【51Nod1766】树上的最远点对-线段树+树的直径

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,m,first[100010]={0},tot=0;
int st[200010],top=0,dep[100010],pos[100010];
int mnp[200010][21],p[200010];
int seg[400010][2];
ll dis[100010];
struct edge
{
int v,next;
ll d;
}e[200010];

void insert(int a,int b,ll d)
{
e[++tot].v=b;
e[tot].d=d;
e[tot].next=first[a];
first[a]=tot;
}

void dfs(int v,int fa)
{
st[++top]=v;
pos[v]=top;

for(int i=first[v];i;i=e[i].next)
if (e[i].v!=fa)
{
dep[e[i].v]=dep[v]+1;
dis[e[i].v]=dis[v]+e[i].d;
dfs(e[i].v,v);
st[++top]=v;
}
}

void rmq_init()
{
for(int i=1;i<=top;i++)
mnp[i][0]=st[i];
for(int i=1;i<=20;i++)
for(int j=1;j+(1<<i)-1<=top;j++)
{
if (dep[mnp[j][i-1]]<dep[mnp[j+(1<<(i-1))][i-1]])
mnp[j][i]=mnp[j][i-1];
else mnp[j][i]=mnp[j+(1<<(i-1))][i-1];
}
p[1]=0;
for(int i=2;i<=top;i++)
{
if (1<<(p[i-1]+1)<i) p[i]=p[i-1]+1;
else p[i]=p[i-1];
}
}

int rmq(int l,int r)
{
int x=p[r-l+1];
if (dep[mnp[l][x]]<dep[mnp[r-(1<<x)+1][x]])
return mnp[l][x];
else return mnp[r-(1<<x)+1][x];
}

ll dist(int a,int b)
{
int g=rmq(min(pos[a],pos[b]),max(pos[a],pos[b]));
return dis[a]+dis[b]-2ll*dis[g];
}

void merge(int a1,int a2,int b1,int b2,int &s1,int &s2)
{
ll ans=0;
if (dist(a1,a2)>ans) ans=dist(a1,a2),s1=a1,s2=a2;
if (dist(a1,b1)>ans) ans=dist(a1,b1),s1=a1,s2=b1;
if (dist(a1,b2)>ans) ans=dist(a1,b2),s1=a1,s2=b2;
if (dist(a2,b1)>ans) ans=dist(a2,b1),s1=a2,s2=b1;
if (dist(a2,b2)>ans) ans=dist(a2,b2),s1=a2,s2=b2;
if (dist(b1,b2)>ans) ans=dist(b1,b2),s1=b1,s2=b2;
}

void pushup(int no)
{
merge(seg[no<<1][0],seg[no<<1][1],seg[no<<1|1][0],seg[no<<1|1][1],seg[no][0],seg[no][1]);
}

void buildtree(int no,int l,int r)
{
if (l==r)
{
seg[no][0]=seg[no][1]=l;
return;
}
int mid=(l+r)>>1;
buildtree(no<<1,l,mid);
buildtree(no<<1|1,mid+1,r);
pushup(no);
}

void query(int no,int l,int r,int s,int t,int &ans1,int &ans2)
{
if (l>=s&&r<=t)
{
merge(ans1,ans2,seg[no][0],seg[no][1],ans1,ans2);
return;
}
int mid=(l+r)>>1;
if (s<=mid) query(no<<1,l,mid,s,t,ans1,ans2);
if (t>mid) query(no<<1|1,mid+1,r,s,t,ans1,ans2);
}

int main()
{
scanf("%d",&n);
for(int i=1;i<n;i++)
{
int x,y;
ll z;
scanf("%d%d%lld",&x,&y,&z);
insert(x,y,z),insert(y,x,z);
}

top=0;
dep[1]=dis[1]=0;
dfs(1,0);
rmq_init();

buildtree(1,1,n);
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
int a,b,c,d;
scanf("%d%d%d%d",&a,&b,&c,&d);
int a1=a,a2=a,b1=c,b2=c;
ll ans=0;
query(1,1,n,a,b,a1,a2);
query(1,1,n,c,d,b1,b2);
ans=max(ans,dist(a1,b1));
ans=max(ans,dist(a1,b2));
ans=max(ans,dist(a2,b1));
ans=max(ans,dist(a2,b2));
printf("%lld\n",ans);
}

return 0;
}
posted @ 2018-08-06 10:59  Maxwei_wzj  阅读(133)  评论(0编辑  收藏  举报