【BZOJ2870】—最长道路Tree(边分治)
边分治比点分治好的一点就是每次分出来都只有2个集合
如果遇到难以合并的信息的时候边分治就很有用了
手动转二叉树
每次可以按照权值大小排序后对两个集合双指针扫两遍
具体实现可以看代码
复杂度
#include<bits/stdc++.h>
using namespace std;
const int RLEN=1<<20|1;
#define ll long long
#define pb push_back
#define pii pair<int,int>
#define gc getchar
inline int read(){
char ch=gc();
int res=0,f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?res:-res;
}
const int N=200005;
const int inf=1e9;
int n,pn,mx,mxsiz,tot,rt;
ll ans;
int adj[N],nxt[N<<1],to[N<<1],siz[N],val[N<<1],vis[N<<1],cnt=1,pt[2],a[N];
pii tmp[2][N];
#define fi first
#define se second
inline bool comp(const pii &a,const pii &b){
return a.fi>b.fi;
}
vector<int> son[N];
inline void addedge(int u,int v,int w){
nxt[++cnt]=adj[u],adj[u]=cnt,to[cnt]=v,val[cnt]=w;
}
void dfs(int u,int f){
for(int e=adj[u];e;e=nxt[e]){
int v=to[e];
if(v==f)continue;
son[u].pb(v),dfs(v,u);
}
}
inline void rebuild(){
cnt=1;memset(adj,0,sizeof(adj));
for(int u=1;u<=n;u++){
if(son[u].size()<=2){
for(int i=0,len=son[u].size();i<len;i++){
int v=son[u][i];
addedge(u,v,v<=pn),addedge(v,u,v<=pn);
}
}
else{
int f1=++n,f2=++n;a[f1]=a[f2]=a[u];
addedge(u,f1,0),addedge(f1,u,0),addedge(f2,u,0),addedge(u,f2,0);
for(int i=0,len=son[u].size();i<len;i++){
if(i&1)son[f2].pb(son[u][i]);
else son[f1].pb(son[u][i]);
}
}
}
}
inline void getrt(int u,int f){
siz[u]=1;
for(int e=adj[u];e;e=nxt[e]){
int v=to[e];
if(vis[e>>1]||v==f)continue;
getrt(v,u),siz[u]+=siz[v];
int k=max(siz[v],mxsiz-siz[v]);
if(k<mx)mx=k,rt=e;
}
}
void getdis(int kd,int u,int f,int dep,int va){
va=min(va,a[u]),tmp[kd][++pt[kd]]=pii(va,dep);
for(int e=adj[u];e;e=nxt[e]){
int v=to[e];
if(vis[e>>1]||v==f)continue;
getdis(kd,v,u,dep+val[e],va);
}
}
void solve(int u,int sz){
mxsiz=sz,mx=inf;
getrt(u,0);
if(mx==inf)return;
int now=rt;vis[now>>1]=1;
pt[0]=pt[1]=0,getdis(0,to[now],0,0,inf),getdis(1,to[now^1],0,0,inf);
sort(tmp[0]+1,tmp[0]+pt[0]+1,comp),sort(tmp[1]+1,tmp[1]+pt[1]+1,comp);
for(int i=1,j=1,mxl=0;i<=pt[0];i++){
while(j<=pt[1]&&tmp[1][j].fi>=tmp[0][i].fi)mxl=max(mxl,tmp[1][j].se),j++;
if(j!=1)ans=max(ans,1ll*tmp[0][i].fi*(mxl+tmp[0][i].se+val[now]+1));
}
for(int i=1,j=1,mxl=0;i<=pt[1];i++){
while(j<=pt[0]&&tmp[0][j].fi>=tmp[1][i].fi)mxl=max(mxl,tmp[0][j].se),j++;
if(j!=1)ans=max(ans,1ll*tmp[1][i].fi*(mxl+tmp[1][i].se+val[now]+1));
}
int ksz=siz[to[now]];solve(to[now],ksz),solve(to[now^1],sz-ksz);
}
int main(){
n=pn=read();
for(int i=1;i<=n;i++)a[i]=read();
for(int i=1;i<n;i++){
int u=read(),v=read();
addedge(u,v,1),addedge(v,u,1);
}
dfs(1,0),rebuild(),solve(1,n);
cout<<ans;
}