CF1470A Strange Birthday Party 题解

题意

\(n\) 个人,第 \(i\) 个人有一个编号 \(k_i\) ,还有 \(m\) 个按价格升序排列的礼物,第 \(i\) 个礼物价格为 \(c_i\) ,对于第 \(i\) 个人,可以给他送前 \(k_i\) 个礼物中的一个,也可以给他送 \(c_{k_i}\) 美元,问最少花费是多少。

分析

根据题意我们不难看出,因为礼物是按价格升序排列的,所以送礼物的花费一定不超过送钱的花费,但是礼物不能重复送,因此我们可以想出贪心策略:尽量先给编号大的人选。我们可以用一个变量来存目前没取过的礼物中编号最靠前的一个,如果最便宜的礼物比送钱的花费更大,就送钱,否则就送礼物。

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll T,n,m,ans;
vector<ll>k;
vector<ll>c;
int main()
{
    scanf("%lld",&T);
    while(T--)
    {
        k.clear();
        c.clear();
        ans=0;
        scanf("%lld%lld",&n,&m);
        ll i,j;
        for(i=0;i<n;i++)
        {
            ll x;
            scanf("%lld",&x);
            x--; //因为是从0存的,所以编号要-1
            k.push_back(x);
        }
        for(i=0;i<m;i++)
        {
            ll x;
            scanf("%lld",&x);
            c.push_back(x);
        }
        sort(k.begin(),k.end(),greater<ll>()); //把k数组按编号降序排列,目的是确保编号大的人能够先选礼物
        j=0; //目前最便宜的礼物的位置
        for(i=0;i<n;i++)
        {
            if(c[j]<c[k[i]]) //送礼物划算
            {
                ans+=c[j++];
            }
            else ans+=c[k[i]]; //送钱划算
        }
        printf("%lld\n",ans);
    }
    return 0;
}
posted @ 2022-02-18 11:09  l_x_y  阅读(20)  评论(0编辑  收藏  举报