• 2019牛客第7场——C(Governing sand)


    Governing sand

    传送门:https://ac.nowcoder.com/acm/contest/887/C
    来源:牛客网

    题意:给了n种树,每种树的个数是p[i],高度是h[i],砍掉每个树花费是c[i]。要求最高的树要严格比总数目的一半多,问砍掉一些树使得条件满足的最小代价。
     
    思路:这个题首先看到数据范围想到要枚举每一种树作为最高的树,这样必然要先把比它高的全都砍掉,排完序后这个可以通过一个后缀和解决,
    然后就是砍掉一些比他小的树,使条件满足。
    因为后缀和已经处理出砍掉了多少树,而且所有树的总数已知,那么砍掉多少棵树就很显然
    K=sum-2*x+1
    最后处理砍掉的树的代价最小,直接根据每棵树代价大小把它插入到应该在的位置,这样树状数组上的点的代价就是一个单调的,二分求砍到第几种树即可。
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=2e5+5;
    const ll inf=0x3f3f3f3f3f3f3f;
    struct node
    {
        ll w;
        int pos,h,p;
    }a[N];
    map<int,ll>m;
    map<int,int>zz;
    int n,b[N];
    ll sum[N],num[N],cnt[N],C,W[N];
    ll ask_w(int x)
    {
        ll ans=0;
        for(;x;x-=x&(-x)) ans+=sum[x];
        return ans;
    }
    ll ask_num(int x)
    {
        ll ans=0;
        for(;x;x-=x&(-x)) ans+=num[x];
        return ans;
    }
    void add_w(int x,ll y)
    {
        for(;x<=n;x+=x&(-x)) sum[x]+=y;
    }
    void add_num(int x,ll y)
    {
        for(;x<=n;x+=x&(-x)) num[x]+=y;
    }
    bool cmp(node x,node y)
    {
        return x.w<y.w;
    }
    bool cmp2(node x,node y)
    {
        return x.h<y.h;
    }
    int main()
    {
        while(~scanf("%d",&n))
        {
            memset(num,0,sizeof num);
            memset(sum,0,sizeof sum);
            memset(W,0,sizeof W);
            memset(cnt,0,sizeof cnt);
            m.clear();
            C=0;
            for(int i=1;i<=n;i++)
            {
                scanf("%d%lld%lld",&a[i].h,&a[i].w,&a[i].p);
                a[i].pos=i;
            }
            sort(a+1,a+1+n,cmp);
            for(int i=1;i<=n;i++) b[a[i].pos]=i;
            sort(a+1,a+1+n,cmp2);
            for(int i=1;i<=n;i++)
            {
                zz[b[a[i].pos]]=i;
            }
            ll ans=inf;
            ll las=0;
            for(int i=n;i>=1;i--)
            {
                m[a[i].h]+=a[i].p;
                if(i!=n&&a[i].h==a[i+1].h)
                {
                    cnt[i]=cnt[i+1];
                    W[i]=W[i+1];
                    las+=a[i].p*a[i].w;
                }
                else
                {
                    cnt[i]=cnt[i+1]+m[a[i+1].h];
                    W[i]=W[i+1]+las;
                    las=a[i].p*a[i].w;
                }
                C+=a[i].p;
            }
            for(int i=1;i<=n;i++)
            {
                int l=0,r=n;
                ll tmp=W[i],k=max(0ll,C-cnt[i]-2*m[a[i].h]+1);
                if(a[i].h==a[i-1].h)
                {
                    add_w(b[a[i].pos],a[i].w*a[i].p);
                    add_num(b[a[i].pos],a[i].p);
                    continue;
                }
                while(l<r)
                {
                    int mid=(l+r)/2;
                    if(ask_num(mid)>=k)
                    {
                        r=mid;
                    }
                    else l=mid+1;
                }
                tmp+=ask_w(max(0,l-1));
                k-=ask_num(max(0,l-1));
                tmp+=k*a[zz[l]].w;
                ans=min(ans,tmp);
                add_w(b[a[i].pos],a[i].w*a[i].p);
                add_num(b[a[i].pos],a[i].p);
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
     
  • 相关阅读:
    random(1)
    django(1)
    python复习
    bootstrap(1)
    jquery(2)
    Jquery(3)
    day17 正则表达式 re模块
    文字笔记
    MATLAB之数学建模:深圳市生活垃圾处理社会总成本分析
    MATLAB之折线图、柱状图、饼图以及常用绘图技巧
  • 原文地址:https://www.cnblogs.com/Suiyue-Li/p/11323522.html
Copyright © 2020-2023  润新知