HDU 多校 6609 第三场 Find the answer (简单贪心)

这题是原来cf上的一道原题,不过对于有一些数据范围修改了,不过还是很好想的

题意:给定一个长度为N的数组,对于数组中的每个位置,满足当前和小于M所需要去掉的最小代价

分析:对于当前是否需要进行去掉一些值,可以采取贪心的方法,对每次加入进来的数进行排序,当前是否需要删除一些值取决于当前的所有值的和,当超过M时,贪心的去除最大的,不过对于当前情况需要去掉多少个才能将该元素加入,不过考虑到对于后面元素的影响,所以去掉的不一定是之前的元素,我们真正要去掉的是将元素加入之后的值。

具体原因如下:当加入的值比当前保存值的最大值小的时候,考虑到后面的元素如果需要进行删除操作,删除当前加入的值一定比删除当前保存值的最大值优,所以需要将后面的元素删除。当加入的值比当前保存值的最大值大或相等时,删去谁都可以,故此时保证答案的正确性。

具体使用mutiset来维护,multiset是<set>库中一个非常有用的类型,它可以看成一个序列,插入一个数,删除一个数都能够在O(logn)的时间内完成,所以很优秀,使用也很方便

具体代码:

#include<bits/stdc++.h>
using namespace std;

const int maxn=2e5+7;
int a[maxn];
multiset<int>ss;

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        ss.clear();
        long long int n,m;
        scanf("%lld%lld",&n,&m);
        for(int i=0;i<n;i++)
        {
            scanf("%d",&a[i]);
        }
        long long int sum=0;
        int tem=0;
        for(int i=0;i<n;i++)
        {
            long long int suma=sum;
            int jishu=0;
            if(suma+a[i]>m)
            {
                auto j=ss.end();
                while(suma+a[i]>m)
                {
                    j--;
                    suma-=*j;
                    jishu++;
                }
            }
            printf("%d ",jishu+tem);
            ss.insert(a[i]);
            auto j=ss.end();
            sum+=a[i];
            while(sum>m)
            {
                j--;
                sum-=*j;
                ss.erase(ss.find(*j));
                tem++;
            }
        }
        printf("
");
    }
}
View Code
原文地址:https://www.cnblogs.com/plys/p/11266762.html