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;
}