• 【BZOJ2870】—最长道路Tree(边分治)


    传送门


    边分治比点分治好的一点就是每次分出来都只有2个集合
    如果遇到难以合并的信息的时候边分治就很有用了

    手动转二叉树

    每次可以按照权值大小排序后对两个集合双指针扫两遍
    具体实现可以看代码

    复杂度O(nlog2n)O(nlog^2n)

    #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;
    }
    
  • 相关阅读:
    改造vue-quill-editor: 结合element-ui上传图片到服务器
    webpack2.X、Vue学习以及将两者相结合
    Vuex-一个专为 Vue.js 应用程序开发的状态管理模式
    vue深究第一弹:computed与watch的异同
    管理系统列表和详情配置
    Vue和vue-template-compiler版本之间的问题
    vuex 闲置状态重置方案
    mac install brew
    Android——推断Service是否已经启动
    【android】uses-permission和permission具体解释
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/11145551.html
Copyright © 2020-2023  润新知