codeforces 994B 贪心+multiset容器优化

http://codeforces.com/problemset/problem/994/B

题目很容易理解,就是有n个骑士,他们都有自己的战斗值,而且每个人的身上都有一定的硬币,每个骑士是可以杀掉战斗值比自己小的骑士并能够得到他的硬币,但是每个骑士不能杀超过k个人,求每个骑士可以获得的最大钱数。

这道题是一道贪心题,开始我以为,局部最优,开始将所有的骑士的硬币数从大到小的顺序排一遍,然后每次都从最大硬币持有者开始遍历一遍,两层for循环,但是w了,不知道为什么,但是这道题目的n太大,就算是不W也会TLE,所以靠改变,用multiset或者优先队列(但优先队列不好遍历),来做,首先要将这些骑士的战斗值从小到大sort一下,然后将后n-k+1个人放进容器里(priority_queue或者multiset),为什么是n-k+1,下面会解释。

我们是将所有的战斗值从小到大排序的,因此第i个人一定能打败前i个人,这里是不会打败人数超过k个,这里就要解释一下为什么是n-k+1个人放入容器里,因为第k+1个人是没有选择能力去杀战斗值比自己大的人,所以第k+1个人只能杀掉前k个,不管所得硬币或多或少,然后剩下的n-k+1个人就可以有选择的找硬币多的人,然后击败他(容器是一个从小到大排硬币的数量的),得到自己可以获得的最多硬币。

#include<bits/stdc++.h>
using namespace std;
int n,m,w;
const int maxn =15;
typedef long long ll;
struct node
{
    ll c;
    int id;
    ll victem;
    bool operator < (const node &a)const
    {
        return victem<a.victem;
    }
}num[100005];
bool cmp1(node a,node b)
{
    return a.victem>b.victem;
}
bool cmp2(node a,node b)
{
    return a.id<b.id;
}
multiset <int> ms;
multiset <int> ::iterator it;
ll ans[100005];
ll num1[100005];
int main()
{
    int n,k;
    cin>>n>>k;
    for(int i=1;i<=n;i++)
        cin>>num[i].victem,num[i].id=i;
    for(int i=1;i<=n;i++)
        cin>>num[i].c;
    sort(num+1,num+n+1);
    k++;
    for(int i=1;i<=n;i++)
    {
        if(i<=k)
            num1[i]+=num1[i-1]+num[i].c,ms.insert(num[i].c);
            else
            {
                ms.erase(ms.begin());//multiset里面始终有三个值,去掉最小的一个,然后
                num1[i]=num[i].c;//加上身下的不就是能够得到的最大值吗
                for(it=ms.begin();it!=ms.end();it++)
                    num1[i]+=*it;
                ms.insert(num[i].c);
            }
            ans[num[i].id]=num1[i];
    }
    for(int i=1;i<=n;i++)
        cout<<ans[i]<<" ";
    cout<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/c___c18/article/details/81590068
今日推荐