[Bzoj 2870] длинная дорога дерево

титульный

Боковые перегородки

Точки Пограничные и точка, чтобы найти центр тяжести по сравнению с краевыми точками, после рассмотрения всех путей этого края, этот край после отключения Unicom разделен на два блока, продолжая раздел

Поскольку каждый фокус раздел находится на одной стороне, он будет иметь только два блока China Unicom, China Unicom рассмотрел два субблоков явно лучше, чем изображение точки рассматривается как более легко блокировать Unicom

Однако, краевые точки имеют проблему в том , что он встречается Самозапирающиеся фиги хризантемы, сложность становится \ (O (N ^ 2) \)

Отметим также сложность краевых точек и степень каждой точки отношений, поэтому мы строим несколько виртуальных точек и виртуального края, это дерево становится бинарное дерево, эта сложность \ (O (п \ OperatorName { LOGN}) \)

Специфический подход, если он найден, как узел с двумя сынами, два на новых виртуальных точках, по словам его сына после этих точек четности для двух сынов

Для этого вопроса, виртуальная точка устанавливаются , чтобы указать правильную точку своего отца, виртуальный краем правой стороны \ (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