CF1077E Thematic Contests 题解
Thematic Contests
题意
有
现在要举办一些比赛,要求:
- 一场比赛中所有题目的分类相同。
- 所有比赛的分类是互不相同的。
- 第一场比赛的题目数量任意,但从第二场开始,每一场比赛的题目数量都必须是前一场的两倍。
求所有比赛的题目数量之和的最大值。
思路
一看数据范围,就知道要离散化。
有一个明显的贪心:按照每个分类的出现次数排序。把出现次数较少的分类放在后面是不可能使答案更优的,所以可以排序。
(温馨提示:接下来的部分中第
我的做法是 dp
。
- 状态:
,表示第 种主题选择 道题情况下,前 种主题选择的题目数量最大值。 - 转移:
。 - 目标状态:
,其中 表示离散化后主题的数量, 表示第 个主题中的题目数量。
但是很明显,二维状态存不下、转移时直接查找会 TLE
,怎么办呢?
我们可以把最后一次比赛选择
具体实现看代码。
Code
点击查看代码
#include <iostream> #include <algorithm> using namespace std; const int N = 2e5 + 10; int n, a[N], m, b[N], c[N], dp[N], ans; // c[i] 用来记录最后一次比赛选择 i 道题的最大答案 int main(){ ios::sync_with_stdio(0), cin.tie(0); cin >> n; for (int i = 1; i <= n; i++) { cin >> a[i]; } // 以下内容为离散化 sort(a + 1, a + n + 1); for (int i = 1; i <= n; i++) { if (a[i] == a[i - 1]) { b[m]++; } else { b[++m] = 1; } } // 接下来是 dp 求答案 sort(b + 1, b + m + 1); // 按出现次数从小到大排序 for (int i = 1; i <= m; i++) { for (int j = 1; j <= b[i]; j++) { // 离散化后第 i 个主题选择了 j 个题目 dp[j] = 0; if (!(j % 2)) { // j 是偶数,那么它的前面还可以添加比赛 dp[j] = c[j / 2]; } dp[j] += j; // 加上这次选择的题目数量 ans = max(ans, dp[j]); // 统计答案 } for (int j = 1; j <= b[i]; j++) { c[j] = max(c[j], dp[j]); // 注意细节!这里的最大值是不可以放在上面去更新的! } } cout << ans; return 0; }
本文作者:wnsyou の blog
本文链接:https://www.cnblogs.com/wnsyou-blog/p/17410400.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步