1. 程式人生 > >牛客網wannafly23 D 漂亮的公園

牛客網wannafly23 D 漂亮的公園

color div endif code problem spa long uniq open

/*
  Source   : 牛客網wannafly23 D 漂亮的公園
  Problem  : 給定一個樹,每個節點有一個顏色,詢問兩個顏色之間的最大距離
  Solution : 可以先求出同一種顏色c的直徑x,y,這另外一個點u到這種顏色c的最大值,一定是x和y中的一個。於是答案只需要枚舉兩種不同顏色的4個點。
             對於同種顏色的集合的維護,可以通過同樣的思想,每次把當前點和前面維護集合裏的點比較,更新一下。
  Date     : 2018-09-03-21.41
*/
#include <bits/stdc++.h>
using namespace std;

typedef 
long long LL; const int MAXN=100005; const LL MOD7 = 1e9+7; vector<int> g[MAXN]; vector<int> color[MAXN]; vector<int> d; map<int,int> mp; int a[MAXN]; int f[MAXN][20]; int dep[MAXN]; int n; int m; void dfs(int u,int pre) { f[u][0]=pre; for (int v:g[u]) { if (v==pre) continue
; dep[v]=dep[u]+1; dfs(v, u); } } void build() { for (int j=1;j<20;++j) { for (int i=1;i<=n;++i) { if (f[i][j-1]) { f[i][j]=f[f[i][j-1]][j-1]; } } } } int LCA(int u,int v) { if (dep[u]<dep[v]) swap(u,v);
int ans=0; int delta=dep[u]-dep[v]; ans += delta; for (int i=0;i<20;++i) { if (delta&(1<<i)) u = f[u][i]; } if (u==v) return ans; for (int i=19;i>=0;--i) { if (f[u][i]!=f[v][i]) { u=f[u][i]; v=f[v][i]; ans += (2<<i); } } return ans+2; } int main() { #ifndef ONLINE_JUDGE freopen("test.txt","r",stdin); #endif // ONLINE_JUDGE scanf("%d%d",&n,&m); int u,v; for (int i=1;i<=n;++i) { scanf("%d",&a[i]); d.push_back(a[i]); } sort(d.begin(),d.end()); int len = unique(d.begin(),d.end())-d.begin(); for (int i=1;i<=len;++i) { mp[d[i-1]]=i; } for (int i=1;i<=n;++i) { a[i]=mp[a[i]]; } for (int i=1;i<n;++i) { scanf("%d%d",&u,&v); g[u].push_back(v); g[v].push_back(u); } dfs(1, 0); build(); for (int i=1;i<=n;++i) { if (color[a[i]].size()<2) { color[a[i]].push_back(i); } else { u=color[a[i]][0]; v=color[a[i]][1]; int d1 = LCA(u, i); int d2 = LCA(v, i); int d3 = LCA(u, v); int d=max({d1, d2, d3}); color[a[i]].clear(); if (d1==d) { color[a[i]].push_back(u); color[a[i]].push_back(i); } else if (d2==d) { color[a[i]].push_back(v); color[a[i]].push_back(i); } else if (d3==d) { color[a[i]].push_back(u); color[a[i]].push_back(v); } } } // for (int i=1;i<10;++i) // { // printf("%d: ",i); // for (int v:g[i]) // printf("%d ",v); // printf("\n"); // } for (int i=1;i<=m;++i) { scanf("%d%d",&u,&v); if (mp.find(u)==mp.end() || mp.find(v)==mp.end()) { printf("0\n"); continue; } u=mp[u]; v=mp[v]; int ans=0; for (int x:color[u]) for (int y:color[v]) ans=max(ans, LCA(x,y)); printf("%d\n",ans); } return 0; }

牛客網wannafly23 D 漂亮的公園