2200+专项:B2. Maximum Control (medium)(dfs序)

original: http://codeforces.com/problemset/problem/958/B2

question:

Give you a tree with n points, you choose some points, and count the number of points that in the simple path of two chosen points.

Print the maximum of number by chosen 1,2…n points.

analyze:

It’s obvious that the chosen points is leaves.

Firstly, find the two farthest points, use one point in their path as root to build the tree.

We could maintain every leave’s value, that means if you choose this leave, the addition you could get.

By give every point a dfs-index, you can deal the value of the leaves in a subtree by Segment Tree easily.

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
#define F double
#define LL long long
#define mid (l+r>>1)
#define ls (rt<<1)
#define rs ((rt<<1)|1)
const int maxn=100009;
#define pill pair<int,int>

int tr[maxn<<2];
int laz[maxn<<2];
void down(int rt,int l,int r){
    if(laz[rt]){
        laz[ls]+=laz[rt];
        laz[rs]+=laz[rt];
        tr[ls]+=laz[rt];
        tr[rs]+=laz[rt];
        laz[rt]=0;
    }
}
void update(int rt,int l,int r,int L,int R,int v){
    if(l>=L&&r<=R){
        tr[rt]+=v;
        laz[rt]+=v;
        return;
    }
    down(rt,l,r);
    if(L<=mid)update(ls,l,mid,L,R,v);
    if(R>mid)update(rs,mid+1,r,L,R,v);
    tr[rt]=max(tr[ls],tr[rs]);
}
pill query(int rt,int l,int r,int L,int R){
    if(l>=L&&r<=R){
        if(l==r)
            return {tr[rt],l};
        down(rt,l,r);
        if(tr[ls]==tr[rt])
            return query(ls,l,mid,L,R);
        else
            return query(rs,mid+1,r,L,R);
    }
    pill ans={-1,0};
    down(rt,l,r);
    if(L<=mid)ans=query(ls,l,mid,L,R);
    if(R>mid)ans=max(ans,query(rs,mid+1,r,L,R));
    return ans;
}



int head[maxn],to[maxn<<1],nex[maxn<<1],now;
int deg[maxn];
void add(int a,int b){
    nex[++now]=head[a];head[a]=now;to[now]=b;
}
int dfsn[maxn],idn,dep[maxn],fa[maxn],siz[maxn];
int fin[maxn];
int n,rt,ll,rr;

void init(int p,int Fa,int d){
    fa[p]=Fa;
    dep[p]=d;
    siz[p]=1;
    dfsn[p]=++idn;
    fin[idn]=p;
    for(int i=head[p];i;i=nex[i]){
        int u=to[i];
        if(u==Fa)continue;
        init(u,p,d+1);
        siz[p]+=siz[u];
    }
}

void cut(int p){//**
    int now=query(1,1,n,dfsn[p],dfsn[p]).first;
    update(1,1,n,dfsn[p],dfsn[p],-now);
    int pre=p;
    p=fa[p];
    now--;

    while(1){
        if(now==0)break;
        for(int i=head[p];i;i=nex[i]){
            int u=to[i];
            if(u==pre||u==fa[p])continue;
            update(1,1,n,dfsn[u],dfsn[u]+siz[u]-1,-now);
        }
        pre=p;
        p=fa[p];
        now--;
    }
}

int main(){
    scanf("%d",&n);
    if(n==1)return 0*printf("1\n");
    if(n==2)return 0*printf("1 2\n");
    for(int i=1;i<n;i++){
        int a,b;scanf("%d%d",&a,&b);
        add(a,b);
        add(b,a);
        deg[a]++;deg[b]++;
    }
    init(1,-1,1);
    int ma=-1;
    for(int i=1;i<=n;i++){
        if(dep[i]>ma)ma=dep[i],ll=i;
    }
    init(ll,-1,1);
    ma=-1;
    for(int i=1;i<=n;i++){
        if(dep[i]>ma)ma=dep[i],rr=i;
    }
    rt=fa[rr];
    int ans=dep[rr];
    printf("%d %d ",1,dep[rr]);

    //--------------------------------------------------------
    idn=0;
    init(rt,-1,1);
    for(int i=1;i<=n;i++){
        if(deg[i]==1){
            update(1,1,n,dfsn[i],dfsn[i],dep[i]);
        }
    }
    cut(ll);
    cut(rr);
    /*printf("\nrt ll rr: %d %d %d\n",rt,ll,rr);
    for(int i=1;i<=n;i++){
        printf("%d : %d\n",i,query(1,1,n,dfsn[i],dfsn[i]).first);
    }*/
    int ct=2;
    if(ans<n)
    while(1){
        pill p=query(1,1,n,1,n);
        ans+=p.first;
        printf("%d ",ans);
        ct++;
        if(ans==n)break;
        cut(fin[p.second]);
    }
    for(int i=ct+1;i<=n;i++)printf("%d%c",n,(i==n?'\n':' '));
}

猜你喜欢

转载自blog.csdn.net/jk_chen_acmer/article/details/90579491