• 洛谷1552 [APIO2012]派遣


    洛谷1552 [APIO2012]派遣


    原题链接


    题解

    luogu上被刷到了省选/NOI- 。。。不至于吧
    这题似乎有很多办法乱搞?
    对于一个点,如果他当管理者,那选的肯定是他子树中薪水最少的k个,而且这k个薪水之和<=m
    k又要最大
    可以维护n个可并堆(代码里是斜堆(不会左偏树)(平衡树启发式合并也行???))
    每次dfs所有儿子,搞完以后再把儿子的堆与键值为自己薪水的节点全部merge起来,然后一直弹最大的弹到和<=m为止,然后用堆的size*L更新答案。
    用大根堆维护。


    Code

    // It is made by XZZ
    #include<cstdio>
    #include<algorithm>
    #define Fname "dispatching"
    using namespace std;
    #define rep(a,b,c) for(rg int a=b;a<=c;a++)
    #define drep(a,b,c) for(rg int a=b;a>=c;a--)
    #define erep(a,b) for(rg int a=fir[b];a;a=nxt[a])
    #define il inline
    #define rg register
    #define vd void
    typedef long long ll;
    il int gi(){
        rg int x=0;rg char ch=getchar();
        while(ch<'0'||ch>'9')ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x;
    }
    typedef struct node* point;
    point null;
    struct node{
        int value,tot;
        ll sum;
        point ls,rs;
        node(int _v){value=_v,ls=rs=null,sum=value,tot=1;}
        il vd reset(){sum=ls->sum+rs->sum+value,tot=ls->tot+rs->tot+1;}
    };
    point merge(point a,point b){
        if(a==null)return b;
        if(b==null)return a;
        if(a->value>b->value){a->rs=merge(a->rs,b);swap(a->ls,a->rs);a->reset();return a;}
        else{b->rs=merge(b->rs,a);swap(b->ls,b->rs);b->reset();return b;}
    }
    int n,m;
    const int maxn=100100;
    int id,fir[maxn],nxt[maxn],dis[maxn];
    int w[maxn],l[maxn];
    point s[maxn];
    point la,lb;
    il vd add(int a,int b){nxt[++id]=fir[a],fir[a]=id,dis[id]=b;}
    ll ans=0;
    il vd dfs(int now){
        erep(i,now)dfs(dis[i]),s[now]=merge(s[now],s[dis[i]]);
        while(s[now]->sum>m){
    	la=s[now]->ls,lb=s[now]->rs;
    	delete s[now];
    	s[now]=merge(la,lb);
        }
        ans=max(ans,(ll)s[now]->tot*l[now]);
    }
    int main(){
        freopen(Fname".in","r",stdin);
        freopen(Fname".out","w",stdout);
        n=gi(),m=gi();
        int b;
        gi(),w[1]=gi(),l[1]=gi();
        rep(i,2,n)b=gi(),w[i]=gi(),l[i]=gi(),add(b,i);
        null=new node(0);
        null->ls=null->rs=null;
        null->tot=null->sum=0;
        rep(i,1,n)s[i]=new node(w[i]);
        dfs(1);
        printf("%lld
    ",ans);
        return 0;
    }
    

    PS.开long long...
  • 相关阅读:
    UVALive 6044(双连通分量的应用)
    hdu 3760(2次bfs求最短路)
    zoj 3370(二分+二分图染色)
    sgu 326(经典网络流构图)
    hdu 4291(矩阵+暴力求循环节)
    uva 11381(神奇的构图、最小费用最大流)
    hdu 4685(匹配+强连通分量)
    hdu 4496(并查集)
    hdu 4722(记忆化搜索)
    Linux安装Nginx使用负载均衡
  • 原文地址:https://www.cnblogs.com/xzz_233/p/7509111.html
Copyright © 2020-2023  润新知