1 条题解
-
0
自动搬运
来自洛谷,原作者为

niuniudundun
天禄搬运于
2025-08-24 21:16:53,当前版本为作者最后更新于2024-12-13 18:34:49,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
题目大意
有 种武器和 种强化材料。第 种强化材料会适配第 种武器,小杨可以花费 金币将该材料对应的适配武器修改为任意武器。小杨最喜欢第 种武器,因此他希望适配该武器的强化材料种类数严格大于其他的武器,请你帮小杨计算为了满足该条件最少需要花费多少金币。
解法
假设结果为 。
可以用数组 表示适配第 种武器的所有材料花费,然后用 表示共有 适配第 种武器的材料,你也可以理解为 的长度。
随后,开贪,既然要求最少花费,那么就将 小的排在前,极易证明,如果不把 小的排在前,求花费时加不到 ( 中最小值),花费就不是最小的。
排序后,核心来了。定义 为遍历 种强化材料的循环变量。因为题面有:
小杨最喜欢第 种武器,因此他希望适配该武器的强化材料种类数严格大于其他的武器,请你帮小杨
计算为了满足该条件最少需要花费多少金币。
所以我们尽量使用 中材料多的, 中最便宜的材料,使用这种材料将第 种武器改成第 种武器,随后 判断当前花费和 取最小值,即 。
如何算当前花费呢?先令 ( 表示当前花费)并定义数组 表示最便宜的材料有那些。因为要让第 种武器适配该武器的强化材料种类数尽可能多,必然会产生一个单调上升序列:。假设 指序列中的数(对应代码中 函数的形参),如果 是负数,说明 中的长度比 短,如果比 长, 加上花费即可。
假设 是 中减去 加一的长度,然后将 的数值加入到 中。 指的是 的长度,所以每轮循环 。但是如果 是负数, 就小了,所以 。
最后对 进行排序, 加上 前 个数,然后 和 进行比较 取小的。
最后开
long long就行了。代码
#include<iostream> #include<bits/stdc++.h> #include<algorithm> using namespace std; const int maxm=1001,maxn=maxm; long long n,m,p[maxn],c[maxm]; long long cnt[maxn]; vector<int> cs[maxn]; long long ans=1e18; long long f(int ii){ long long curcnt=cnt[1],res=0; vector<int> tmp; for(int i=2;i<=n;i++){ int b=max((int)(cs[i].size()-ii+1),0); for(int j=0;j<b;j++){ res+=cs[i][j]; } curcnt+=b; for(int j=b;j<cs[i].size();j++){ tmp.push_back(cs[i][j]); } } sort(tmp.begin(),tmp.end()); for(int i=0;i<ii-curcnt;i++){ res+=tmp[i]; } return res; } int main(){ cin>>n>>m; for(int i=1;i<=m;i++){ cin>>p[i]>>c[i]; cnt[p[i]]++; cs[p[i]].push_back(c[i]); } for(int i=1;i<=n;i++){ sort(cs[i].begin(),cs[i].end()); } for(int i=max((long long)(cnt[1]),1ll);i<=m;i++){//注意范围! ans=min(ans,f(i)); } cout<<ans<<endl; return 0; }
- 1
信息
- ID
- 11084
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 3
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者