Big Problems for Organizers CodeForces - 418D (貪心,直徑)
阿新 • • 發佈:2019-02-24
ace inf fine def ios 端點 pop 討論 cpp
大意: 給定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); } }
Big Problems for Organizers CodeForces - 418D (貪心,直徑)