[Bzoj 2870]最長の道路の木

タイトル

サイドパーティション

エッジ点と点がエッジ点に比べて重心を見つけることであり、このエッジのすべてのパスを考慮した後、切断ユニコム後、このエッジは、2つのブロックに分割し、継続的なパーティション

各パーティションフォーカスが一方の側にあるので、それが唯一のチャイナユニコムの二つのブロックを有するであろう、中国ユニコムは、2つのサブブロックをユニコムより容易と考え像点よりも明らかに良好ブロックであると考えられ

それは自己閉鎖図菊に遭遇することにしかし、エッジ点は問題がある、複雑になる\(O(N ^ 2) \)

我々はまた、エッジ点の複雑さとの関係の各点の度合いに注意し、私たちは、いくつかの仮想点及び仮想エッジを構築、このツリーは二分木なり、この複雑である\(O(n個の\ operatorname { LOGN})\)

それが発見された場合は、特定のアプローチは、どのように2人の息子にこれらのパリティ・ポイントの後に彼の息子によると2人の息子、新しい仮想ポイント上の2つのノードと、

この質問のために、仮想点は、その父、右側の仮想エッジの右側の点指すように設定されている\(0 \)を、我々は二つのブロック内の各パスユニコムは、整理、ダブルポインタをスイープ以下のような戦いを戦います

コード

#include<bits/stdc++.h>
#define re register
#define LL long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
inline int read() {
    char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
    while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
}
const int maxn=2e5+5;
struct E{int v,nxt,w;}e[maxn<<1];
int head[maxn],n,num,sum[maxn],vis[maxn];
int rn,S,top[2],Mnow,tax[maxn],rt,val[maxn];
struct Seg{int l,v;}st[2][maxn];
std::vector<int> son[maxn];LL ans;
inline int cmp(const Seg &A,const Seg &B) {return A.v<B.v;}
inline void add(int x,int y,int w) {
    e[++num].v=y;e[num].nxt=head[x];head[x]=num;e[num].w=w;
}
void dfs1(int x,int fa) {
    for(re int i=head[x];i;i=e[i].nxt) {
        if(e[i].v==fa) continue;
        son[x].push_back(e[i].v);
        dfs1(e[i].v,x);
    }
}
void getrt(int x,int fa) {
    sum[x]=1;
    for(re int i=head[x];i;i=e[i].nxt) {
        if(vis[i>>1]||e[i].v==fa) continue;
        getrt(e[i].v,x);sum[x]+=sum[e[i].v];
        int now=max(sum[e[i].v],S-sum[e[i].v]);
        if(now<Mnow) Mnow=now,rt=i;
    }
}
void dfs2(int o,int x,int fa,int l,int v) {
    v=min(v,val[x]);st[o][++top[o]]=(Seg){l,v};
    for(re int i=head[x];i;i=e[i].nxt) {
        if(e[i].v==fa||vis[i>>1]) continue;
        dfs2(o,e[i].v,x,l+e[i].w,v);
    }
}
void solve(int x,int sz) {
    Mnow=maxn;S=sz;getrt(x,0);
    if(Mnow==maxn) return;
    int now=rt;vis[rt>>1]=1;
    top[0]=0;dfs2(0,e[now].v,0,0,maxn);
    top[1]=0;dfs2(1,e[now^1].v,0,0,maxn);
    std::sort(st[0]+1,st[0]+top[0]+1,cmp);
    std::sort(st[1]+1,st[1]+top[1]+1,cmp);
    tax[top[1]]=st[1][top[1]].l;int j=1;
    for(re int i=top[1]-1;i;--i) tax[i]=max(st[1][i].l,tax[i+1]);
    for(re int i=1;i<=top[0];i++) {
        while(st[1][j].v<st[0][i].v&&j<=top[1]) j++;
        if(j<=top[1]&&st[1][j].v>=st[0][i].v) 
            ans=max(ans,1ll*st[0][i].v*(e[now].w+st[0][i].l+tax[j]+1));
    }
    tax[top[0]]=st[0][top[0]].l;j=1;
    for(re int i=top[0]-1;i;--i) tax[i]=max(st[0][i].l,tax[i+1]);
    for(re int i=1;i<=top[1];i++) {
        while(st[0][j].v<st[1][i].v&&j<=top[0]) j++;
        if(j<=top[0]&&st[0][j].v>=st[1][i].v) 
            ans=max(ans,1ll*st[1][i].v*(e[now].w+st[1][i].l+tax[j]+1));
    }
    int ss=sz-sum[e[now].v];
    solve(e[now].v,sum[e[now].v]);solve(e[now^1].v,ss);
}
int main() {
    n=rn=read();
    for(re int i=1;i<=n;i++) val[i]=read();
    for(re int x,y,i=1;i<n;i++) 
        x=read(),y=read(),add(x,y,0),add(y,x,0);
    dfs1(1,0);
    num=1;memset(head,0,sizeof(head));
    for(re int i=1;i<=n;i++) {
        int sz=son[i].size();
        if(!sz) continue;
        if(sz==1) {
            add(i,son[i][0],son[i][0]<=rn);
            add(son[i][0],i,son[i][0]<=rn);
            continue;
        }
        if(sz==2) {
            add(i,son[i][0],son[i][0]<=rn);add(son[i][0],i,son[i][0]<=rn);
            add(i,son[i][1],son[i][1]<=rn);add(son[i][1],i,son[i][1]<=rn);
            continue;
        }
        int t1=++n,t2=++n;val[t1]=val[t2]=val[i];
        add(i,t1,0),add(t1,i,0);add(i,t2,0),add(t2,i,0);
        for(re int j=0;j<son[i].size();j++) 
            if(j&1) son[t1].push_back(son[i][j]);
                else son[t2].push_back(son[i][j]);
    }
    solve(1,n);
    std::cout<<ans;
}

おすすめ

転載: www.cnblogs.com/asuldb/p/11299968.html