2019牛客(第七场)C.Governing sand

题目链接、

题意:

给你n种树,每种树有p[i]个,每个去掉花费c[i],树高h[i]

让你去掉一些树,使得最高的树的个数占总数的一半以上

题解:

从高到底枚举树(相同高度看为一种),计算出需要去掉多少,然后二分即可

 

一直错的原因:top=Q.top()忘记写了、

 

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5+7;
struct node{
    ll P,C,H;//count,cost,height
    bool operator < (const node f)const{
        return C<f.C;
    }
}a[maxn];
ll sum[maxn],n;
ll Sum[maxn];
void add(ll pos,ll x,ll y){
    while(pos<=n){
        sum[pos] += x,Sum[pos] += y;
        pos+=pos&-pos;
    }
}
ll query(ll pos,ll ans = 0){
    while(pos)ans += sum[pos],pos-=pos&-pos;
    return ans;
}
ll queryValue(ll pos,ll ans = 0){
    while(pos)ans += Sum[pos],pos-=pos&-pos;
    return ans;
}
int main(){
    while(~scanf("%lld",&n)){
        for(ll i=1;i<=n;i++)scanf("%lld%lld%lld",&a[i].H,&a[i].C,&a[i].P);
        sort(a+1,a+1+n);
        priority_queue<pair<ll,ll> >Q;
        ll last = 0,Ans = 2e18;
        for(ll i=1;i<=n;i++){
            add(i,a[i].P,a[i].P*a[i].C);
            Q.push(make_pair(a[i].H,i));
        }
        while(!Q.empty()){
            ll Sum = 0,Cst = 0;
            pair<ll,ll> top = Q.top();
            Q.pop();
            ll pos = top.second;
            Sum += a[pos].P;
            Cst += a[pos].C*a[pos].P;
            add(pos,-a[pos].P,-a[pos].P*a[pos].C);
            while(!Q.empty() && top.first == Q.top().first){
                top = Q.top();
                pos = top.second;
                add(pos,-a[pos].P,-a[pos].P*a[pos].C);
                Sum += a[pos].P;
                Cst += a[pos].C*a[pos].P;
                Q.pop();
            }
            ll Need = query(n)-Sum+1,cost = last;
            //printf("%lld %lld %lld\n",query(n),Sum,Need);
            if(Need>0){
                ll l = 1,r = n,sul = n;
                while(l<=r){
                    ll mid = l+r>>1;
                    if(query(mid)>=Need)
                        r = mid-1,sul = mid;
                    else
                        l = mid+1;
                }
                //printf("sul : %d \n",sul);
                ll cnt = Need-query(sul);
                cost += queryValue(sul-1)+(a[sul].P+cnt)*a[sul].C;
            }
            Ans = min(Ans,cost);
            last += Cst;
        }
        printf("%lld\n",Ans);
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值