• BZOJ5152: [Wc2018]通道


    BZOJ5152: [Wc2018]通道

    https://lydsy.com/JudgeOnline/problem.php?id=2466

    分析:

    • 边分治+虚树。
    • (dis1(x,y)+d2x+d2y-2 imes d2lca+dis3(x,y))
    • (w_x=dc_x+d2_x)其中(dc)表示分治中心到(x)的距离。
    • 转化成最大化(w_x+w_y-2 imes d2lca+dis3(x,y)) ((x,y))位于不同分治中心且不同子树内。
    • (w_x+w_y+dis3(x,y))相当于直径+点权。子树内维护颜色为(0/1)的直径两端点向上合并。
    • 如果求lca都用st表,边分治那里把点集按tree2的dfs序排序改成归并,时间复杂度就是(O(nlog n))

    代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cstdlib>
    #include <vector>
    #include <iostream>
    #include <cmath>
    #include <set>
    #include <vector>
    #include <iostream>
    using namespace std;
    #define N 100050
    #define db(x) cerr<<#x<<" = "<<x<<endl
    #define rep(n) for(i=1;i<=n;i++)
    #define FV(x) for(i=head[x];i;i=nxt[i])
    #define gun() exit(0)
    typedef long long ll;
    int n,a[N],c[N],is[N];
    ll w[N],ans;
    ll t3dis(int,int);
    struct A {
    	int to; ll v;
    };
    vector<A>V[N];
    void solve();
    char buf[100000],*p1,*p2;
    #define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
    int id[N];
    int rd() {
    	int x=0; char s=nc();
    	while(s<'0') s=nc();
    	while(s>='0') x=(((x<<2)+x)<<1)+s-'0',s=nc();
    	return x;
    }
    ll rdl() {
    	ll x=0; char s=nc();
    	while(s<'0') s=nc();
    	while(s>='0') x=(((x<<2)+x)<<1)+s-'0',s=nc();
    	return x;
    }
    int tmp[N];
    struct Edge_Tree {
    	#define M 200050
    	int head[M],to[M<<1],nxt[M<<1],cnt,m;ll val[M<<1];
    	int fk[M<<1],siz[M],root,vis[M<<1],tot;
    	void init() {m=n; cnt=1; fk[0]=1<<30;}
    	inline void add(int u,int v,ll w) {
    		to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; val[cnt]=w;
    	}
    	void rb(int x,int y) {
    		int i,lim=V[x].size(),lst=0,so=0;
    		for(i=0;i<lim;i++) if(V[x][i].to!=y) {
    			int t=V[x][i].to;ll v=V[x][i].v;
    			so++;
    			if(so==1) {
    				add(x,t,v); add(t,x,v); lst=x;
    			}else if(so==lim-(x!=1)) {
    				add(lst,t,v); add(t,lst,v);
    			}else {
    				m++; add(lst,m,0); add(m,lst,0); add(m,t,v); add(t,m,v); lst=m;
    			}
    		}
    		for(i=0;i<lim;i++) if(V[x][i].to!=y) rb(V[x][i].to,x);
    	}
    	void gr(int x,int y) {
    		int i;siz[x]=1;
    		FV(x) if(to[i]!=y&&!vis[i]) {
    			gr(to[i],x);
    			fk[i]=max(tot-siz[to[i]],siz[to[i]]);
    			if(fk[i]<fk[root]) root=i;
    			siz[x]+=siz[to[i]];
    		}
    	}
    	void gd(int x,int y,ll d,int o) {
    		if(x<=n) {
    			is[x]=1; w[x]=d; c[x]=o;
    		}int i;
    		FV(x) if(to[i]!=y&&!vis[i]) {
    			gd(to[i],x,d+val[i],o);
    		}
    	}
    	void edc(int x,int l,int r) {
    		if(l>=r)return ;
    		root=0; gr(x,0);
    		int p=root,i; vis[p]=vis[p^1]=1;
    		a[0]=0;
    		gd(to[p],0,val[p],1);
    		gd(to[p^1],0,0,2);
    		for(i=l;i<=r;i++) a[++a[0]]=id[i];
    		solve();		
    		int al=tot,sz=siz[to[p]];
    		int t=l-1;
    		for(i=l;i<=r;i++) if(c[id[i]]==1) tmp[++t]=id[i];
    		int mid=t;
    		for(i=l;i<=r;i++) if(c[id[i]]==2) tmp[++t]=id[i];
    		for(i=l;i<=r;i++) id[i]=tmp[i];
    		tot=sz; edc(to[p],l,mid);
    		tot=al-sz; edc(to[p^1],mid+1,r);
    	}
    	void read() {
    		init();
    		int i,x,y;ll z;
    		rep(n-1)x=rd(),y=rd(),z=rdl(),V[x].push_back((A){y,z}),V[y].push_back((A){x,z});
    		rb(1,0);
    	}
    	void Wk() {
    		tot=m; edc(1,1,n);
    	}
    }t1;
    inline bool cmp2(int,int);
    struct Virtual_Tree {
    	int head[N],to[N<<1],nxt[N<<1],cnt,e[N<<1],dfn[N],dep[N],f[20][N<<1],Lg[N<<1];
    	ll dis[N],val[N<<1];
    	int S[N],tp,p[N][3][2];
    	inline void add(int u,int v,ll w) {
    		to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; val[cnt]=w;
    	}
    	inline void add(int u,int v) {
    		to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt;
    	}
    	inline int cmp(int x,int y) {return dep[x]<dep[y]?x:y;}
    	void d1(int x,int y) {
    		int i;
    		dfn[x]=++dfn[0]; f[0][dfn[0]]=x;
    		FV(x) if(to[i]!=y) {
    			dis[to[i]]=dis[x]+val[i]; dep[to[i]]=dep[x]+1; d1(to[i],x); f[0][++dfn[0]]=x;
    		}
    	}
    	int lca(int l,int r) {
    		l=dfn[l],r=dfn[r]; if(l>r)swap(l,r); int len=Lg[r-l+1]; return cmp(f[len][l],f[len][r-(1<<len)+1]);
    	}
    	void read() {
    		int i,x,y,j; ll z;
    		rep(n-1)x=rd(),y=rd(),z=rdl(),add(x,y,z),add(y,x,z);
    		dep[1]=1; d1(1,0);Lg[0]=-1;rep(dfn[0])Lg[i]=Lg[i>>1]+1;
    		rep(n)id[i]=i;
    		sort(id+1,id+n+1,cmp2);
    		int lim=dfn[0];
    		for(i=1;(1<<i)<=lim;i++) for(j=1;j+(1<<i)-1<=lim;j++) f[i][j]=cmp(f[i-1][j],f[i-1][j+(1<<(i-1))]);
    		memset(head,0,sizeof(head));
    	}
    	ll calc(int x,int y) {
    		if((!x)||(!y)) return 0;
    		return w[x]+w[y]+t3dis(x,y);
    	}
    	void dp(int x) {
    		int i,o;
    		p[x][1][0]=p[x][1][1]=p[x][2][0]=p[x][2][1]=0;
    		if(is[x]) p[x][c[x]][0]=x;
    		FV(x) {
    			int t=to[i];
    			dp(t);
    			for(o=1;o<3;o++) {
    				int q=3-o;
    				ans=max(ans,max(calc(p[x][o][0],p[t][q][0])
    						   ,max(calc(p[x][o][1],p[t][q][0])
    						   ,max(calc(p[x][o][1],p[t][q][1])
    						   ,    calc(p[x][o][0],p[t][q][1]))))   -2*dis[x]);
    			}
    			for(o=1;o<3;o++) {
    				if(!p[x][o][0]) {
    					p[x][o][0]=p[t][o][0];
    					p[x][o][1]=p[t][o][1];
    					continue;
    				}
    				if(!p[t][o][0]) {
    					continue;
    				}
    				ll t1=calc(p[x][o][0],p[x][o][1]);
    				ll t2=calc(p[x][o][0],p[t][o][0]);
    				ll t3=calc(p[x][o][0],p[t][o][1]);
    				ll t4=calc(p[x][o][1],p[t][o][0]);
    				ll t5=calc(p[x][o][1],p[t][o][1]);
    				ll t6=calc(p[t][o][0],p[t][o][1]);
    				ll mx=max(t1,max(t2,max(t3,max(t4,max(t5,t6)))));
    				if(t2==mx) {
    					p[x][o][1]=p[t][o][0];
    				}else if(t3==mx) {
    					p[x][o][1]=p[t][o][1];
    				}else if(t4==mx) {
    					p[x][o][0]=p[x][o][1]; p[x][o][1]=p[t][o][0];
    				}else if(t5==mx) {
    					p[x][o][0]=p[x][o][1]; p[x][o][1]=p[t][o][1];
    				}else if(t6==mx) {
    					p[x][o][0]=p[t][o][0]; p[x][o][1]=p[t][o][1];
    				}
    			}
    		}
    		head[x]=is[x]=0;
    	}
    	void Wk() {
    		cnt=0;
    		int i,x,y;
    		S[tp=1]=1;
    		rep(a[0]) {
    			w[a[i]]+=dis[a[i]];
    			x=a[i],y=lca(x,S[tp]);
    			while(dep[y]<dep[S[tp]]) {
    				if(dep[y]>=dep[S[tp-1]]) {
    					add(y,S[tp]); tp--;
    					if(S[tp]!=y) S[++tp]=y;
    					break;
    				}add(S[tp-1],S[tp]); tp--;
    			}if(S[tp]!=x) S[++tp]=x;
    		}while(tp>1)add(S[tp-1],S[tp]),tp--;
    		dp(1);
    	}
    }t2;
    void solve() {t2.Wk();}
    inline bool cmp2(int x,int y) {return t2.dfn[x]<t2.dfn[y];}
    struct Dis_Tree {
    	int head[N],to[N<<1],nxt[N<<1],cnt,e[N<<1],dfn[N],dep[N],f[20][N<<1],Lg[N<<1];
    	ll dis[N],val[N<<1];
    	inline void add(int u,int v,ll w) {
    		to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; val[cnt]=w;
    	}
    	int cmp(int x,int y) {return dep[x]<dep[y]?x:y;}
    	void d1(int x,int y) {
    		int i;
    		dfn[x]=++dfn[0]; e[dfn[0]]=x; f[0][dfn[0]]=x;
    		for(i=head[x];i;i=nxt[i]) if(to[i]!=y) {
    			dis[to[i]]=dis[x]+val[i]; dep[to[i]]=dep[x]+1; d1(to[i],x); e[++dfn[0]]=x; f[0][dfn[0]]=x;
    		}
    	}
    	int lca(int l,int r) {
    		l=dfn[l],r=dfn[r]; if(l>r) swap(l,r); int len=Lg[r-l+1]; return cmp(f[len][l],f[len][r-(1<<len)+1]);
    	}
    	void read() {
    		int i,x,y,j; ll z;
    		rep(n-1)x=rd(),y=rd(),z=rdl(),add(x,y,z),add(y,x,z);
    		dep[1]=1; d1(1,0);Lg[0]=-1;rep(dfn[0])Lg[i]=Lg[i>>1]+1;
    		int lim=dfn[0];
    		for(i=1;(1<<i)<=lim;i++) for(j=1;j+(1<<i)-1<=lim;j++) f[i][j]=cmp(f[i-1][j],f[i-1][j+(1<<(i-1))]);
    	}
    }t3;
    ll t3dis(int x,int y) {return t3.dis[x]+t3.dis[y]-2*t3.dis[t3.lca(x,y)];}
    int main() {
    	n=rd();
    	t1.read(); t2.read(); t3.read();
    	t1.Wk();
    	printf("%lld
    ",ans);
    }
    
  • 相关阅读:
    制作USB启动盘
    Custom Content and Formatting 富文本框批量上传 quill
    “从特殊到一般”的思想
    每个元素应该有 相同的概率 被返回。
    前缀和
    graphql 案例
    电脑关机后怎么计算时间 CMOS电池 时钟芯片 晶体振荡器 晶振 时钟晶振 谐振电容
    前端质量|基于业务驱动的前端性能有效实践案例
    Pull or Push
    分区表出现错误 分区错误
  • 原文地址:https://www.cnblogs.com/suika/p/10205571.html
Copyright © 2020-2023  润新知