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);
}