[ABC143F] Distinct Numbers

传送门

解答

官方题解:

\[\begin{aligned} f(X) &= \left\lfloor\frac{\sum_{j=1}^N \min\{C_j, X\}}{X}\right\rfloor &= \left\lfloor\frac{\sum_{k=0}^N \min\{k, X\}\times D_k}{X}\right\rfloor &= \left\lfloor\frac{\sum_{k=0}^X kD_k + X\sum_{k=X+1}^N D_k}{X}\right\rfloor \end{aligned} \]

之后找满足\(K\le f(X)\)的最大\(X\)即可。

我的思路:
如果\(K\)为定值,可以\(O(\log N)\)求出答案:

  1. 二分答案,只需检查答案\(X\)是否“合法”。
  2. 获得每个数出现次数cnt其中每个数的出现次数ccnt
  3. 有贪心易知,每次只要取出现次数前\(K\)多的数即可。又易知每个数最多被使用\(X\)次。
  4. 若共有\(Y\)个数\(出现次数\ge K\),设其余的数之和为\(Z\),只需检查\(数的个数\ge K\)与\(Z+K\times Y \ge X\times K\)。

实现

如果直接实现的话,是\(O(n\log n)\)的,那么可不可以优化到\(O(n)\)呢?

  1. 由于答案满足单调性,从上一个答案开始逐一枚举判断就可以做到\(O(n)\)了。我的代码
  2. ccntans处分为两半:LR。可以求出在每个ans处的最大K代码
  3. 考虑将\(\ge ans\)的数全部“拦腰截断”,设置为\(ans\)。可以求出\(出现次数\ge ans\)的数的个数。倒序枚举\(K\),从上一次递增枚举ans
上一篇:JS实现数组去重方法总结(六种方法)


下一篇:c++this指针与explicit