1774: [Usaco2009 Dec]Toll 过路费
1704: [Usaco2007 Mar]Face The Right Way

1787: [Ahoi2008]Meet 紧急集合

高橋直樹 posted @ 2013年3月25日 14:53 in BZOJ with tags bzoj AHOI , 836 阅读

http://www.lydsy.com/JudgeOnline/problem.php?id=1787

RunID User Problem Result Memory Time Language Code_Length Submit_Time
375404 Liu_Ts 1787 Accepted 45732 kb 7584 ms C++ 2039 B 2013-03-25 11:25:27

 

题意

一棵树,每次询问给三个点,求一个点使得到这三个点的距离和最小。

题解

理解一下,可知答案必定在这三个点中,某两个点的LCA上,

于是枚举a,b;a,c;b,c的LCA。

最后发现这三个LCA有规律,有两个一定相同,但是不会用。

LCA写的RMQ比较慢啊

 

#include<cstring>
#include<climits>
#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=500001,M=1000001,Q=2000002;

int q[Q],d[N],tot,n,k,v[M],next[M],head[N],num[N],m;

struct SegmentTree
{
	int m[6000002];
	void update(int x)
	{
		int l=x<<1,r=l+1;
		m[x]=m[l];
		if(d[m[x]]>d[m[r]])
			m[x]=m[r];
	}
	void build(int x,int s,int t)
	{
		if(s==t)
		{
			m[x]=q[s];return;
		}
		int mid=s+t>>1;
		build(x<<1,s,mid);build((x<<1)+1,mid+1,t);
		update(x);
	}
	int get(int x,int s,int t,int ll,int rr)
	{
		if(ll<=s&&t<=rr)	return m[x];
		int t1=0,t2=0,mid=s+t>>1;
		if(ll<=mid)	t1=get(x<<1,s,mid,ll,rr);
		if(rr>mid)	t2=get((x<<1)+1,mid+1,t,ll,rr);
		if(d[t1]<d[t2])	return t1;
		else return t2; 
	}
}a;
void add(int x,int y)
{
	v[++k]=y;next[k]=head[x];head[x]=k;
}
void dfs(int x,int fa,int deep)
{
	q[++q[0]]=x;num[x]=q[0];d[x]=deep;
	for(int i=head[x];i;i=next[i])
		if(v[i]!=fa)
			dfs(v[i],x,deep+1),q[++q[0]]=x;
}
int lca(int x,int y)
{
	if(num[x]>num[y])	swap(x,y);
	return a.get(1,1,q[0],num[x],num[y]);	
}
int main()
{
	scanf("%d%d",&n,&m);int x,y,z;
	for(int i=1;i<n;i++)
	{
		scanf("%d%d",&x,&y);
		add(x,y);add(y,x);
	}
	dfs(1,0,0);d[0]=INT_MAX;
	a.build(1,1,q[0]);
	int p,q;
	while(m--)
	{
		int ans,sum=INT_MAX;
		scanf("%d%d%d",&x,&y,&z);
		int s=d[x]+d[y]+d[z];
		p=lca(x,y);q=lca(p,z);
		if(s-d[q]*2-d[p]<sum)
			sum=s-d[q]*2-d[p],ans=p;
		p=lca(x,z);
		if(s-d[q]*2-d[p]<sum)
			sum=s-d[q]*2-d[p],ans=p;
		p=lca(y,z);
		if(s-d[q]*2-d[p]<sum)
			sum=s-d[q]*2-d[p],ans=p;
		printf("%d %d\n",ans,sum);
	}
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter