首页 > 其他分享 >CF1077E Thematic Contests 题解

CF1077E Thematic Contests 题解

时间:2023-05-17 21:47:29浏览次数:48  
标签:Thematic 题目 比赛 limits int 题解 CF1077E max dp

Thematic Contests

题意

有 \(n\) 个问题,每个问题有一个分类 \(a_i\)。

现在要举办一些比赛,要求:

  • 一场比赛中所有题目的分类相同。
  • 所有比赛的分类是互不相同的。
  • 第一场比赛的题目数量任意,但从第二场开始,每一场比赛的题目数量都必须是前一场的两倍。

求所有比赛的题目数量之和的最大值。

思路

一看数据范围,就知道要离散化。

有一个明显的贪心:按照每个分类的出现次数排序。把出现次数较少的分类放在后面是不可能使答案更优的,所以可以排序。

(温馨提示:接下来的部分中第 \(i\) 种主题指的都是离散化后的。)

我的做法是 dp

  • 状态:\(dp_{i,j}\),表示第 \(i\) 种主题选择 \(j\) 道题情况下,前 \(i\) 种主题选择的题目数量最大值。
  • 转移:\(dp_{i,j}=\max\limits_{k=1}^{i-1}\{\max\limits_{l=1,l\times 2=j}^{b_k}\{dp_{k,l} \}\}+j\)。
  • 目标状态:\(\max\limits_{i=1}^{m}\{\max\limits_{j=1}^{b_i}\{dp_{i,j} \}\}\),其中 \(m\) 表示离散化后主题的数量,\(b_i\) 表示第 \(i\) 个主题中的题目数量。

但是很明显,二维状态存不下、转移时直接查找会 TLE,怎么办呢?

我们可以把最后一次比赛选择 \(i\) 道题的最大答案记录下来,这样既可以省掉 \(i\) 这一个维度,还可以节省掉查找的时间,两全其美。

具体实现看代码。

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;
}

标签:Thematic,题目,比赛,limits,int,题解,CF1077E,max,dp
From: https://www.cnblogs.com/lw0-blog/p/17410400.html

相关文章

  • abc235_d Multiply and Rotate 题解
    MultiplyandRotate题意给定两个整数\(a\)和\(n\),有一个整数\(x\),初始值为\(1\),有两种操作:将\(x\)变成\(x\timesa\)。在\(x>10\)且\(x\)不是十的倍数的情况下可以执行此操作:将\(x\)当成一个字符串,将其循环右移一次。求最少执行多少次操作能把\(x\)变......
  • P8786 李白打酒加强版 题解
    李白打酒加强版题目大意一开始酒显里有\(2\)斗酒,每遇到一次店就会把酒显里的酒数量(单位:斗)乘\(2\),每遇到一次花就把酒显里的酒喝掉\(1\)斗。这一路上一共遇到店\(n\)次,遇到花\(m\)次,且最后一次遇到的是花,酒显里没有一斗酒了。计算这一路上遇到店和花的顺序总共有......
  • YACS 2023年5月月赛 甲组 T1 子集和(六) 题解
    YACS老师说这是道分治,但就不告诉我怎么做,我硬是用线段树卡了过去...特别解气的是把AC图片发了过去(我就是在YACS上的编程课)莫队好了说点正经的,看到是谁谁谁的倍数就能想到DP,状态设计也很水啦!设f[i]为当前考虑到的区间内,子集和%k=i的数量。新加入一个元素时,循环0~......
  • CF1183C Computer Game 题解
    ComputerGame还算水的一道题。题意本题意为题面直接翻译的简化版,可能会比题目翻译要复杂。有\(q\)次询问,每次给出四个数,表示一开始的电亮为\(k\),有\(n\)个回合,不插电玩一个回合则电量会减少\(a\),插电玩一个回合则电量会减少\(b\),电量在任何时刻都必须严格大于\(0\)......
  • Plsql或Navicat连接登陆Oracle时慢、执行语句的时候也特别慢的问题解决方案
    用Plsql或Navicat连接登陆Oracle时,等待时间特别长。经过漫长的等待后,执行语句的时候也特别慢,监听配置没毛病的情况下,大概率是监听日志文件过大导致的。监听日志路径:app\Administrator\diag\tnslsnr\LS--20171012URU\listener\trace\listener.log删除listener.log文件即可。......
  • 交通运输(Wormhole Transportaion) 题解
    传送门交通运输(WormholeTransportaion)题目大意有\(n\)个点和\(m\)个点对,你需要构造一张\(m-1\)条边的无向图,使得\(m\)个点对间最短路之和最小。求最小值及取到最小值的方案数。\(2\len\le2000,2\lenm\le2\times10^7,1\leu_i,v_i\len,u_i\neqv_i\)。......
  • P3919 【模板】可持久化线段树 1(可持久化数组) 题解
    一、题目描述:维护这样的一个长度为$n$的数组,支持以下两种操作$1$:在某个历史版本上修改某一个位置上的值$2$:访问某个历史版本上的某一位置的值每进行一次操作,就会生成一个新的版本(对于操作2,生成的就是一个完全一样的版本)。版本编号即为当前操作......
  • 题解:独占访问2 Exclusive Access 2
    题目链接怎么唯一一篇题解这么抽象,完全看不懂给定一张无向图,求给这张图定向成DAG之后的最长路最短是多少。转化一下变成对DAG进行分层,每一层之间的点没有连边,使得层数尽可能少,那么最后的层数就是答案。那么就求出若干个独立集,让独立集总数尽可能少。这是经典的色数问题,我们......
  • GYM102392 简要题解
    自己下午闲着没事单挑了一下,两小时左右一度rk1,但后继无力了。。。。A.MaxorMin肯定沿着出现过的数操作;然后发现如果a[i]=k,a[j]>k,a[k]<k就会增加一次操作所以维护一下差分序列即可。B.LevelUp两维DP,这个疑似edu出过。要注意的是:需要关于x排个序,不然会漏一些转移。D.......
  • AT_dp_s 题解
    题目传送门第一道数位\(\text{dp}\),检验一下自己懂没懂。特别感谢\(\text{yinhee}\)大佬,他的讲解令我受益匪浅。题目分析\(dp_{pos,res,lim}\)为当前枚举到从高位往低位数第\(pos\)位,数字和取模后的余数为\(res\)时的方案数,其中\(lim\)可以理解为一个布尔值,\(0\)表......