Big Problems for Organizers CodeForces - 418D (贪心,直径)

大意: 给定n结点树, m个询问, 每次给出两个旅馆的位置, 求树上所有结点到最近旅馆距离的最大值

 

先考虑一些简单情形.

若旅馆只有一个的话, 显然到旅馆最远的点是直径端点之一

若树为链的话, 显然是直径端点或两旅馆的中点

这样的话思路就来了, 也就是说最远点要么是直径端点, 要么是到两旅馆距离差不超过1的点

实际求的时候并不需要求出具体在那个点取得最大, 只需简单分类讨论一下, 用RMQ预处理一下, O(1)回答询问

 

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <queue>
#define REP(i,a,n) for(int i=a;i<=n;++i)
#define pb push_back
using namespace std;

const int N = 1e5+10, INF = 0x3f3f3f3f;
int n, m, r1, r2, mx;
vector<int> g[N];
int vis[N], fa[N], s[N], dep[N], no[N];
int Log[N], w[N], f[2][20][N];

int bfs(int x) {
	memset(vis, 0, sizeof vis);
	queue<int> q;
	fa[x] = 0, vis[x] = 1, q.push(x);
	while (!q.empty()) {
		x = q.front();q.pop();
		for (int y:g[x]) if (!vis[y]) {
			vis[y] = 1, fa[y]=x, q.push(y);
		}
	}
	return x;
}

void dfs(int x, int fa, int d, int rt) {
	dep[x]=d, no[x]=rt, w[rt] = max(w[rt], d);
	for (int y:g[x]) if (!vis[y]&&y!=fa) {
		dfs(y,x,d+1,rt);
	}
}

int RMQ(int l, int r, int p) {
	if (l>r) return -INF;
	int t = Log[r-l+1];
	return max(f[p][t][l],f[p][t][r-(1<<t)+1]);
}

int main() {
	scanf("%d", &n);
	REP(i,2,n) {
		int u, v;
		scanf("%d%d", &u, &v);
		g[u].pb(v),g[v].pb(u);
	}
	r1 = bfs(1), r2 = bfs(r1);
	memset(vis, 0, sizeof vis);
	for (int i=r2; i; i=fa[i]) { 
		vis[i]=1, s[++*s]=i, no[i]=*s;
	}
	REP(i,1,*s) dfs(s[i],0,0,i);
	Log[0] = -1;
	REP(i,1,n) { 
		f[0][0][i]=w[i]+i,f[1][0][i]=w[i]-i;
		Log[i] = Log[i>>1]+1;
	}
	REP(j,1,19) for (int i=1;i+(1<<j-1)<=n; ++i) {
		f[0][j][i] = max(f[0][j-1][i],f[0][i+(1<<j-1)][j-1]);
		f[1][j][i] = max(f[1][j-1][i],f[1][i+(1<<j-1)][j-1]);
	}
	scanf("%d", &m);
	REP(i,1,m) {
		int x, y, ans;
		scanf("%d%d", &x, &y);
		int l=no[x], r=no[y];
		if (l>r) swap(l,r),swap(x,y);
		if (l==r) {
			printf("%d\n", max(l-1,*s-l)+min(dep[x],dep[y]));
			continue;
		}
		int mid = l+r-dep[x]+dep[y];
		if (mid<=2*l) ans = max(r-1,*s-r)+dep[y];
		else if (mid>=2*r) ans = max(l-1,*s-l)+dep[x];
		else {
			mid /= 2;
			int L=max(l-1,RMQ(l+1,mid,0)-l)+dep[x];
			int R=max(*s-r,RMQ(mid+1,r-1,1)+r)+dep[y];
			ans = max(L,R);
		}
		printf("%d\n", ans);
	}
}

 

上一篇:Codeforces Round #555 (Div. 3) D. N Problems During K Days 【数学思维】


下一篇:Mtk平台Update部分Metadata值