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

猜你喜欢

转载自www.cnblogs.com/suika/p/10205571.html