CF1839B题解

  • 分析

    根据题意,对于所有\(a=x\)的灯,我们最多可以一次开\(x\)盏。

    最优方案一定是只开\(a\)相同的灯,因为开一盏大的会使等于\(a\)的灯少开一盏,而且最后不会坏掉,会一直占着一个名额,从而使当前\(a\)一直到更大的\(a\)的轮次一直少开一盏,这个亏损必定大于等于多开一盏大\(a\)轮次的灯所带来的利益(因为不提前开这个灯在他自己的\(a\)的轮次还是可以开包括这个灯在内的\(a\)盏灯,而提前开这个灯就不会在自己的轮次开,而且只能开\(a-1\)盏,所以总利润还是\(a\)盏灯的利润,而且提前的轮数到当前的轮数会一直亏损一盏灯的利润,所以亏损必定大于等于利润),所以不开大的,小的可以看做在小的轮次里面开大的,这已经知道是必定不赚的决策了,所以只开\(a\)相同的。

    显然对于所有\(a=x\)的灯,我们选\(b\)最大的\(x\)盏灯就行,注意到\(b\)最大为\(1e9\),所以开long long。

  • 代码

#include <iostream>
#include <vector>
#include <algorithm>
#define int long long
using namespace std;
constexpr int MAXN(1000007);
vector <int> e[MAXN];
int T, n;
inline void read(int &temp) { cin >> temp; }
inline bool cmp(int x, int y) { return x > y; }
inline void work() {
	for (int i(1); i <= n; ++i)  e[i].clear();
	int ans(0);
	read(n);
	for (int i(1), a, b; i <= n; ++i)  read(a), read(b), e[a].push_back(b);
	for (int i(1); i <= n; ++i)  sort(e[i].begin(), e[i].end(), cmp);
	for (int i(1); i <= n; ++i) {
		if (!e[i].size())  continue;
		for (int j(0); j < min(i, (int)e[i].size()); ++j)  ans += e[i][j];
	}
	cout << ans << endl;
}
signed main() {
	ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
	read(T);
	while (T--)  work();
	return 0;
}

posted @ 2023-10-23 10:06  Kazdale  阅读(220)  评论(0编辑  收藏  举报