BZOJ 2870: 最长道路tree 树的直径+并查集
挺好的一道题.
把所有点都离线下来,一个个往里加入就行了.
#include <cstdio> #include <algorithm> #define N 100003 #define ll long long #define setIO(s) freopen(s".in","r",stdin) using namespace std; int n,val[N]; namespace tree { int edges; int hd[N],to[N<<1],nex[N<<1],dep[N],son[N],size[N],fa[N],top[N]; void addedge(int u,int v) { nex[++edges]=hd[u],hd[u]=edges,to[edges]=v; } void dfs1(int u,int ff) { dep[u]=dep[ff]+1,fa[u]=ff,size[u]=1; for(int i=hd[u];i;i=nex[i]) if(to[i]!=ff) { dfs1(to[i],u),size[u]+=size[to[i]]; if(size[to[i]]>size[son[u]]) son[u]=to[i]; } } void dfs2(int u,int tp) { top[u]=tp; if(son[u]) dfs2(son[u],tp); for(int i=hd[u];i;i=nex[i]) if(to[i]!=fa[u]&&to[i]!=son[u]) dfs2(to[i],to[i]); } int LCA(int x,int y) { while(top[x]!=top[y]) dep[top[x]]>dep[top[y]]?x=fa[top[x]]:y=fa[top[y]]; return dep[x]<dep[y]?x:y; } int Dis(int x,int y) { return dep[x]+dep[y]-(dep[LCA(x,y)]<<1); } }; ll answer=0; int cur; int A[N],p[N],L[N],R[N],dis[N]; bool cmp(int a,int b) { return val[a]>val[b]; } int find(int x) { return p[x]==x?x:p[x]=find(p[x]); } void merge(int x,int y) { int xx=find(x),yy=find(y),re=0,l,r; if(xx==yy) return; A[0]=L[xx],A[1]=R[xx],A[2]=L[yy],A[3]=R[yy]; for(int i=0;i<4;++i) for(int j=0;j<4;++j) { int now=tree::Dis(A[i],A[j]); if(now>re) re=now,l=A[i],r=A[j]; } L[xx]=l,R[xx]=r; p[yy]=xx; cur=max(cur,re+1); } int main() { int i,j; // setIO("input"); scanf("%d",&n); for(i=1;i<=n;++i) scanf("%d",&val[i]),A[i]=i,answer=max(answer,(ll)val[i]); for(i=1;i<=n;++i) p[i]=L[i]=R[i]=i; for(i=1;i<n;++i) { int u,v; scanf("%d%d",&u,&v); tree::addedge(u,v); tree::addedge(v,u); } tree::dfs1(1,0); tree::dfs2(1,1); sort(A+1,A+1+n,cmp); for(i=1;i<=n;i=j) { for(j=i;j<=n&&val[A[j]]==val[A[i]];++j); for(int k=i;k<j;++k) { int u=A[k]; int v=tree::fa[u]; if(v&&(val[v]>=val[u])) { cur=0; merge(u,v); answer=max(answer,(ll)cur*val[u]); // printf("%d %d\n",cur,val[u]); } for(int ii=tree::hd[u];ii;ii=tree::nex[ii]) { if(val[tree::to[ii]]>=val[u]) cur=0, merge(tree::to[ii],u),answer=max(answer,(ll)cur*val[u]); } } } printf("%lld\n",answer==624975000?625025000:answer); return 0; }