zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    门头沟PHP,java编程兴趣小组欢迎大家的加入。
    mysql数据库怎么存入emoji表情,更改utf8mb4后为什么出现全是问号
    Laravel发送邮件配置-问题解决
    php版本低更换php版本-问题以解决
    极光客户互动云java post请求
    【问题解决】增加https后 phpcms 分页错误
    阿里云阿里免费ssl wap网站在手机微信、手机浏览器无法访问
    Kali Linux on Android # 实测:小米2s离线安装Kali Linux
    3-1 LVS-NAT集群
    使用LVM方式安装Ubuntu 16.04
  • 原文地址:https://www.cnblogs.com/dreagonm/p/10514657.html
Copyright © 2011-2022 走看看