jzoj3690. 【CF418D】Big Problems for Organizers/codeforces418D

題目描述

Description
2214年“Russian Code Cup”的最終決賽將在n 座賓館裏舉行。其中的兩座賓館(讓我們稱它們爲主賓館)將要主辦所有的活動,並且剩下的賓館將會容納所有參賽者。這些賓館被總共n-1 條道路連接,使得你能從任一座賓館到達另外任意一座。

組委會想要知道,如果通過一條連接兩座賓館的道路耗費一單位時間,並且每個參賽者的目的地是距離他們自己最近的主賓館之一;那麼,所有參賽者同時出發,最後所有人均到達目的地的最少所需時間爲多少。

委員在研究很多種主賓館分佈的方案。對於每種方案,幫助委員會找到最少所需時間。

Input
第一行包含一個整數n(2 <= n <= 100000)——賓館的數量。接下來n-1行每行包含兩個整數——每條路連接的兩座賓館。可以認爲,賓館從1 到n 編號。

接下來的一行包含一個整數m(1<= m <= 100000)——詢問的數量。接下來m 行每行包含兩個不相同的整數——我們假設爲主賓館的賓館編號。

Output
對於每個組委會的請求輸出單獨一個整數——所有參賽者都到達主賓館所需時間。

Sample Input
輸入1:

3

2 3

3 1

3

2 1

2 3

3 1

輸入2:

4

1 4

1 2

2 3

3

1 4

1 3

2 3

Sample Output
輸出1:

1

1

1

輸出2:

2

1

2

Data Constraint
對於30% 的數據,n,m <=1000。

題解

碼農題(1/3)

一種簡單(?)的方法是用LCT維護最大深度,然後貌似要用set。。。
還有一種更簡單(?)的方法
考慮倍增維護
欽定x的深度小於y的深度
那麼x–y的中點一定在x–lca這一段

①y是x的祖先
在這裏插入圖片描述
那麼可以分成如下幾部分計算:
①x的子樹到x+②x~mid上的子樹到x+③mid~y上的子樹到y+④y的祖先的其它子樹到y

②xy沒有祖先關係
在這裏插入圖片描述
答案:①x的子樹到x+②y的子樹到y+③x~mid上的子樹到x+④mid~lca到y+⑤y~lca到y+⑥lca的祖先的子樹到y+⑦lca除x和y所在子樹到y
其中①②⑥可以dp,③④⑤倍增維護,⑦維護每個子樹中前三大
清真

code

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define max(a,b) (a>b?a:b)
using namespace std;

int a[200001][2];
int ls[100001];
int f[100001];
int g[100001];
int g1[100001][17];
int g2[100001][17];
int G[100001][6];
int fa[100001][17];
int d[100001];
int n,Q,i,j,k,l,len,x,y,Lca,ans,s,S,X,Y;

void New(int x,int y)
{
	++len;
	a[len][0]=y;
	a[len][1]=ls[x];
	ls[x]=len;
}

void dfs(int Fa,int t)
{
	int i;
	
	d[t]=d[Fa]+1;
	
	fa[t][0]=Fa;
	fo(i,1,16)
	fa[t][i]=fa[fa[t][i-1]][i-1];
	
	for (i=ls[t]; i; i=a[i][1])
	if (a[i][0]!=Fa)
	{
		dfs(t,a[i][0]);
		f[t]=max(f[t],f[a[i][0]]+1);
	}
}

void Dfs(int Fa,int t)
{
	int i,mx1=0,Mx1=0,mx2=0,Mx2=0;
	
	if (Fa)
	g[t]=max(g[t],g[Fa]+1);
	
	for (i=ls[t]; i; i=a[i][1])
	if (a[i][0]!=Fa)
	{
		if (f[a[i][0]]+2>mx1)
		{
			mx2=mx1;
			Mx2=Mx1;
			mx1=f[a[i][0]]+2;
			Mx1=a[i][0];
		}
		else
		if (f[a[i][0]]+2>mx2)
		{
			mx2=f[a[i][0]]+2;
			Mx2=a[i][0];
		}
		
		if (f[a[i][0]]+1>G[t][0] || f[a[i][0]]+1==G[t][0] && a[i][0]<G[t][1])
		{
			G[t][4]=G[t][2];
			G[t][5]=G[t][3];
			
			G[t][2]=G[t][0];
			G[t][3]=G[t][1];
			
			G[t][0]=f[a[i][0]]+1;
			G[t][1]=a[i][0];
		}
		else
		if (f[a[i][0]]+1>G[t][2] || f[a[i][0]]+1==G[t][2] && a[i][0]<G[t][3])
		{
			G[t][4]=G[t][2];
			G[t][5]=G[t][3];
			
			G[t][2]=f[a[i][0]]+1;
			G[t][3]=a[i][0];
		}
		else
		if (f[a[i][0]]+1>G[t][4] || f[a[i][0]]+1==G[t][4] && a[i][0]<G[t][5])
		{
			G[t][4]=f[a[i][0]]+1;
			G[t][5]=a[i][0];
		}
	}
	
	for (i=ls[t]; i; i=a[i][1])
	if (a[i][0]!=Fa)
	{
		if (a[i][0]==Mx1)
		{
			g[a[i][0]]=mx2;
			Dfs(t,a[i][0]);
		}
		else
		{
			g[a[i][0]]=mx1;
			Dfs(t,a[i][0]);
		}
	}
}

void DFS(int Fa,int t)
{
	int i,mx1=-2133333333,Mx1=0,mx2=-2133333333,Mx2=0;
	
	fo(i,1,16)
	{
		g1[t][i]=max(g1[t][i-1],g1[fa[t][i-1]][i-1]);
		g2[t][i]=max(g2[t][i-1],g2[fa[t][i-1]][i-1]);
	}
	
	for (i=ls[t]; i; i=a[i][1])
	if (a[i][0]!=Fa)
	{
		if (f[a[i][0]]+1>mx1)
		{
			mx2=mx1;
			Mx2=Mx1;
			mx1=f[a[i][0]]+1;
			Mx1=a[i][0];
		}
		else
		if (f[a[i][0]]+1>mx2)
		{
			mx2=f[a[i][0]]+1;
			Mx2=a[i][0];
		}
	}
	
	for (i=ls[t]; i; i=a[i][1])
	if (a[i][0]!=Fa)
	{
		if (a[i][0]==Mx1)
		{
			g1[a[i][0]][0]=mx2-d[t];
			g2[a[i][0]][0]=mx2+d[t];
			
			DFS(t,a[i][0]);
		}
		else
		{
			g1[a[i][0]][0]=mx1-d[t];
			g2[a[i][0]][0]=mx1+d[t];
			
			DFS(t,a[i][0]);
		}
	}
}

int lca(int x,int y)
{
	int i;
	
	if (d[x]<d[y])
	swap(x,y);
	
	fd(i,16,0)
	if (d[fa[x][i]]>=d[y])
	x=fa[x][i];
	
	fd(i,16,0)
	if (fa[x][i]!=fa[y][i])
	{
		x=fa[x][i];
		y=fa[y][i];
	}
	
	if (x!=y)
	x=fa[x][0];
	
	return x;
}

int jump(int t,int s)
{
	int i;
	
	i=0;
	while (s)
	{
		if (s&1)
		t=fa[t][i];
		
		s>>=1;
		++i;
	}
	
	return t;
}

int find1(int t,int s)
{
	int ans=-2133333333;
	int i;
	
	i=0;
	while (s)
	{
		if (s&1)
		{
			ans=max(ans,g1[t][i]);
			t=fa[t][i];
		}
		
		s>>=1;
		++i;
	}
	
	return ans;
}

int find2(int t,int s)
{
	int ans=-2133333333;
	int i;
	
	i=0;
	while (s)
	{
		if (s&1)
		{
			ans=max(ans,g2[t][i]);
			t=fa[t][i];
		}
		
		s>>=1;
		++i;
	}
	
	return ans;
}

int main()
{
//	freopen("S8_10_1.in","r",stdin);
//	freopen("a.in","r",stdin);
//	freopen("b.out","w",stdout);
	
	memset(g1,128,sizeof(g1));
	memset(g2,128,sizeof(g2));
	
	scanf("%d",&n);
	fo(i,2,n)
	{
		scanf("%d%d",&j,&k);
		
		New(j,k);
		New(k,j);
	}
	
	dfs(0,1);
	Dfs(0,1);
	DFS(0,1);
	
	scanf("%d",&Q);
	for (;Q;--Q)
	{
		scanf("%d%d",&x,&y);
		
		if (d[x]<d[y])
		swap(x,y);
		X=x;
		Y=y;
		
		Lca=lca(x,y);
		
		if (Lca==y)
		{
			s=d[x]-d[y];
			ans=max(max(f[x],g[y]),s/2);
			
			S=d[x]+find1(x,s/2);
			ans=max(ans,S);
			
			x=jump(x,s/2);
			S=find2(x,(s+1)/2)-d[y];
			ans=max(ans,S);
		}
		else
		{
			s=d[x]+d[y]-d[Lca]-d[Lca];
			ans=max(max(max(f[x],f[y]),g[Lca]+d[y]-d[Lca]),s/2);
			
			if (d[x]-s/2-d[Lca]>=1)
			{
				S=d[x]+find1(x,s/2);
				ans=max(ans,S);
				
				x=jump(x,s/2);
			}
			else
			{
				S=d[x]+find1(x,d[x]-d[Lca]-1);
				ans=max(ans,S);
				
				x=jump(x,d[x]-d[Lca]-1);
			}
			
			if (d[x]-d[Lca]-1>=1)
			{
				S=find2(x,d[x]-d[Lca]-1)-d[Lca]+(d[Y]-d[Lca]);
				ans=max(ans,S);
			}
			if (d[y]-d[Lca]-1>=1)
			{
				S=d[y]+find1(y,d[y]-d[Lca]-1);
				ans=max(ans,S);
			}
			
//			---
			
			x=jump(x,d[x]-d[Lca]-1);
			y=jump(y,d[y]-d[Lca]-1);
			
			if (f[x]<f[y] || f[x]==f[y] && x>y)
			swap(x,y);
			
			if (x==G[Lca][1] && y==G[Lca][3])
			ans=max(ans,G[Lca][4]+d[Y]-d[Lca]);
			else
			if (x==G[Lca][1])
			ans=max(ans,G[Lca][2]+d[Y]-d[Lca]);
			else
			ans=max(ans,G[Lca][0]+d[Y]-d[Lca]);
		}
		
		printf("%d\n",ans);
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章