• P1552 [APIO2012]派遣


    思路

    复习下左偏树
    左偏树首先满足堆性质,其次定义了一个dis,使得每个点的dis都是右子树dis+1,且左子树的dis>=右子树的dis
    合并过程可以参考FHQ treap的merge进行修改
    一开始看错题了,是选择的人要能跟所有派遣者通信(等价于是选择子树中的点),不是选中一个人使他变得可以与所有人通信
    观察到代价之和领导力和选择的人的数量最多,所以派出人应当数量最多,用大根堆维护这个性质,然后在枚举每个人当作首领的情况,把其他子树合并过来之后继续维护选出数量最多且总和小于m的性质,然后更新ans即可
    记得开longlong

    代码

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #define int long long
    using namespace std;
    struct Node{
        int num,lson,rson,dis,sum,sz,fa;
    }LT[100100];
    int fa[100100],c[100100],L[100100],n,m,ans,root;
    int u[100100<<1],v[100100<<1],fir[100100],nxt[100100<<1],cnt;
    void addedge(int ui,int vi){
        ++cnt;
        u[cnt]=ui;
        v[cnt]=vi;
        nxt[cnt]=fir[ui];
        fir[ui]=cnt;
    }
    void init(void){
        for(int i=1;i<=n;i++){
            LT[i].num=LT[i].sum=c[i];
            LT[i].sz=1;
            LT[i].fa=i;
            LT[i].lson=LT[i].rson=0;
            LT[i].dis=1;
        }
    }
    void pushup(int o){
        LT[o].sum=LT[LT[o].lson].sum+LT[LT[o].rson].sum+LT[o].num;
        LT[o].sz=LT[LT[o].lson].sz+LT[LT[o].rson].sz+1;
    }
    int findroot(int o){
        if(LT[o].fa==o)
            return o;
        return LT[o].fa=findroot(LT[o].fa);
    }
    int merge(int x,int y){
        if((!x)||(!y))
            return x+y;
        if(LT[x].num<LT[y].num)
            swap(x,y);
        LT[x].rson=merge(LT[x].rson,y);
        if(LT[LT[x].lson].dis<LT[LT[x].rson].dis)
            swap(LT[x].lson,LT[x].rson);
        LT[x].dis=LT[LT[x].rson].dis+1;
        LT[LT[x].lson].fa=LT[LT[x].rson].fa=LT[x].fa=x;
        pushup(x);
        return x;
    }
    int top(int x){
        return LT[findroot(x)].num;
    }
    void pop(int x){
        LT[LT[x].lson].fa=LT[x].lson;
        LT[LT[x].rson].fa=LT[x].rson;
        LT[x].fa=merge(LT[x].lson,LT[x].rson);
    }
    void dfs(int x){
        for(int i=fir[x];i;i=nxt[i]){
            if(v[i]==fa[x])
                continue;
            dfs(v[i]);
            merge(findroot(x),findroot(v[i]));
        }
        while(LT[findroot(x)].sum>m)
            pop(findroot(x));
        ans=max(ans,LT[findroot(x)].sz*L[x]);
    }
    signed main(){
        scanf("%lld %lld",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%lld %lld %lld",&fa[i],&c[i],&L[i]);
            if(fa[i]==0)
                root=i;
            else{
                addedge(fa[i],i);
                addedge(i,fa[i]);
            }
        }
        init();
        dfs(root);
        printf("%lld
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    开放平台架构指南
    绝了!起个好标题的9大技巧
    ASP已老,尚能饭否?
    离职,问题就解决了吗?
    什么是草台班子?
    回忆我的第一个软件项目
    Vue3中的Composables组合式函数,Vue3实现minxins
    Vue3中的teleport节点传送
    js中if逻辑过多,常见review优化
    QT安装
  • 原文地址:https://www.cnblogs.com/dreagonm/p/10514657.html
Copyright © 2020-2023  润新知