视频加载失败

安吉D6-T3

1317 字
7 分钟
安吉D6-T3
原题呈现

题目描述#

小信在玩一款卡牌游戏.对方场上有 nn 张怪物卡,第 ii 张怪物的初始血量为 hih_i

小信有两种攻击方式:

  • 群攻:使用一次群攻,会让当前所有存活怪物的血量都减少 11. 如果这次减少后存在至少一只怪物血量变为 00 或更小,这些怪物会立刻死亡,并且群攻效果会立刻再次触发一次(再次让所有仍存活怪物血量减少 11,并且这次额外效果不会消耗群攻次数). 如此反复,只要某一次群攻触发后有怪物死亡,就会继续自动触发下一次群攻;当某一次触发后没有任何怪物死亡时,这张群攻卡牌的效果结束.

  • 普攻:一次普攻可以选择任意一只存活怪物,使其血量减少 11

现在有 qq 次询问.每次询问只给出一个整数 kk,表示本次询问中小信可以使用 kk 次群攻,普攻的使用次数无限制.小信可以以任意顺序穿插使用群攻与普攻,目标是消灭全部怪物,并使总攻击次数最少.

请你对每次询问输出最少需要多少次攻击.

输入格式#

第一行输入一个整数 nn,表示怪物数量.

第二行输入 nn 个整数 h1hnh_1 \sim h_n,表示各怪物初始血量.

第三行输入一个整数 qq,表示询问次数.

接下来 qq 行,每行输入一个整数 kk,表示每次询问中小信的群攻次数限制.

输出格式#

输出 qq 行.每行输出一次询问的答案:在最优策略下最少需要的总攻击次数.

样例#

样例 1#

输入

10
1 3 2 2 6 7 2 1 2 10
9
1
2
3
4
5
6
7
8
9

输出

9
7
5
5
5
5
5
5
5

样例 2#

输入

3
1 1 3
3
3
2
1

输出

2
2
2

数据范围#

本题采用捆绑评测,对于一个子任务,你必须通过其中的所有数据才能得到相应分数.

子任务编号分数n,qn,q特殊性质
12010\le 10
2105000\le 5000hi=nh_i = n
3205000\le 5000
4103×105\le 3\times 10^5hi=nh_i = n
5103×105\le 3\times 10^5q=10q=10
6153×105\le 3\times 10^5
71510610^6

对于所有数据:1n,q1061 \le n,q \le 10^61hi,kn1 \le h_i,k \le n

结论题,结论为:由于值域很小,我们可以将所有数字按值放在一个桶中,桶中所有为 0 的且后面存在非 0 位置的位置视为一个空格.每一次群攻可以消灭一个空格,当场上没有剩余空格时,再进行一次群攻即可消灭全部敌人.

由于群攻总是比普攻不劣,我们先考虑群攻次数足够的情况,此时只需要施展场上空格次数 +1 次群攻即可.

群攻次数不足时呢?我们考虑使用普攻填空格.从后面往前进行遍历,每当遇到一个空格 ii

  • 若该格右边存在:同种血量的怪物存在多种,则选择血量最接近的一种,该种怪物中的一个通过普攻降到血量 ii,来填补这个空格的同时,又不会拆东墙补西墙.
  • 否则,选择当前血量最大的怪兽,通过普攻将其血量变为 ii,用来填补这个空格.

例如:现在存在 2,3,5,7,7,92,3,5,7,7,9,将其整理成桶的形式:10,21,31,40,51,60,72,80,911_0,2_1,3_1,4_0,5_1,6_0,7_2,8_0,9_1,所有不存在(即为空格)的数值为 1,4,6,81,4,6,8

从右边开始:

  • 对于 88,让 99 通过一次普攻变成 88.此时:2,3,5,7,7,82,3,5,7,7,8.代价为 1.
  • 对于 66,让 77 通过一次普攻变成 66.此时:2,3,5,6,7,82,3,5,6,7,8.代价为 1.
  • 对于 44,让 88 通过四次普攻变成 44.此时:2,3,4,5,6,72,3,4,5,6,7.代价为 4.
  • 对于 11,让 77 通过六次普攻变成 11.此时:1,2,3,4,5,61,2,3,4,5,6.代价为 6.

显然,由于存在群攻,这四次填空格的方式并不需要全部操作.只需要贪心的选择其中的部分空格填上,即选择代价最少的几种.因此:将 4 次操作按照代价从小到大排序,在其中选择 4k+14-k+1 项(其中 kk 是允许群攻的次数),所需代价就是普攻的次数,再加上 kk 次群攻即可.

标程

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 100;
int n, h[N], q, a[N];
ll sum[N];
signed main() {
#ifdef ONLINE_JUDGE
freopen("profane.in", "r", stdin);
freopen("profane.out", "w", stdout);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> h[i];
}
sort(h + 1, h + n + 1);
stack<int> stk;
vector<int> vec;
int maxh = -1;
for (int i = 1; i <= n; i++) {
a[h[i]]++;
maxh = max(maxh, h[i]);
}
for (int i = maxh; i >= 1; i--) {
if (a[i] > 1) {
for (int j = 2; j <= a[i]; j++)
stk.push(i);
} else if (a[i] == 0) {
int cost = 0;
if (!stk.empty()) {
int tp = stk.top();
stk.pop();
cost = tp - i;
} else {
cost = maxh - i;
maxh--;
}
vec.push_back(cost);
}
}
sort(vec.begin(), vec.end());
for (int i = 0; i < vec.size(); i++) {
sum[i + 1] = sum[i] + vec[i];
}
cin >> q;
while (q--) {
int k;
cin >> k;
if (k > vec.size()) {
cout << vec.size() + 1 << endl;
} else {
int need = vec.size() - k + 1;
cout << sum[need] + k << endl;
}
}
return 0;
}

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

安吉D6-T3
https://blog.jerrylab.top/posts/problem/anji2026/D6/T3/
作者
Jerry
发布于
2026-08-06
许可协议
CC BY-NC-SA 4.0
Profile Image of the Author
Jerry
Hello, I'm Jerry.
公告
欢迎来到我的博客!这是一则示例公告。
分类
标签
最新动态
站点统计
文章
80
分类
3
标签
35
总字数
89,198
运行时长
0
最后活动
0 天前
站点信息
构建平台
Cloudflare Pages
博客版本
Firefly v6.16.5
文章许可
CC BY-NC-SA 4.0