BZOJ5152: [Wc2018]通道

BZOJ5152: [Wc2018]通道

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

分析:

  • 边分治+虚树。
  • \(dis1(x,y)+d2x+d2y-2\times d2lca+dis3(x,y)\)
  • \(w_x=dc_x+d2_x\)其中\(dc\)表示分治中心到\(x\)的距离。
  • 转化成最大化\(w_x+w_y-2\times d2lca+dis3(x,y)\) \((x,y)\)位于不同分治中心且不同子树内。
  • \(w_x+w_y+dis3(x,y)\)相当于直径+点权。子树内维护颜色为\(0/1\)的直径两端点向上合并。
  • 如果求lca都用st表,边分治那里把点集按tree2的dfs序排序改成归并,时间复杂度就是\(O(n\log 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\n",ans);
}
posted @ 2019-01-01 19:15  fcwww  阅读(150)  评论(0编辑  收藏  举报