专栏文章

题解:P14205 [ROI 2016 Day1] 要塞防御

P14205题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@minl4chq
此快照首次捕获于
2025/12/02 04:11
3 个月前
此快照最后确认于
2025/12/02 04:11
3 个月前
查看原文
贪心。
显然优先守卫 kik_i 更大的防御段,这样单个士兵的贡献更高。
但是该段最后可能剩下不到 kik_i 个敌人,此时最后一个个士兵的贡献会减少。
于是我们使用 map 统计贡献为 xx 的士兵数量 yy,优先选贡献更大的士兵。
在一个防御段中,前 aiki\big \lfloor \frac{a_i}{k_i} \big \rfloor 个士兵的贡献为 kik_i,最后一个士兵的贡献为 aimodkia_i \bmod k_i
按贡献排序后,用敌人总个数减去消灭掉的敌人个数即可。

参考代码:

CPP
#include <bits/stdc++.h>

using namespace std;

#define ll long long
#define PLL pair<ll, ll>

const int N = 300050;

int n, s, a, k;
ll ans;
map<ll, ll> mp;
vector<PLL> cnt;

bool cmp(PLL a, PLL b){
	return a.first > b.first;
}

int main() {
	cin >> n >> s;
	for(int i = 1; i <= n; i ++){
		cin >> a >> k;
		ans += a;
		mp[k] += a / k;
		mp[a % k] ++;
	}
	for(PLL i : mp)
		cnt.push_back(i);
	sort(cnt.begin(), cnt.end(), cmp);
	for(PLL i : cnt){
		if(i.second < s){
			s -= i.second;
			ans -= i.first * i.second;
		}
		else{
			ans -= s * i.first;
			break;
		}
	}
	cout << ans;
	return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...