感谢kadia和CK大佬的耐心讲解
我知道自己菜,但在昨天才知道自己这么菜呜呜
D没过认了,C还是第一次没过,自闭了…
抱怨结束。
同步于这里,来这里观看体验更差哦好哦
一开始想二分,模拟,优先队列,dp啥的乱来的同学注意了
越往复杂的地方想越想不到,没思路了赶紧往简单的地方想
举个例子,这组样例
1 1 1 1 2 3 4 5
明 显 1 这 么 多 , 影 响 答 案 的 肯 定 1 而 不 是 其 他 数 字 明显1这么多,\color{red}{影响答案的肯定1}而不是其他数字 明显1这么多,影响答案的肯定1而不是其他数字
这组样例这么摆放是最优秀的,答案是1
1 2 1 3 1 4 1 5
所以看出策略是以出现最多的数字作为隔板,其他数字填充进去
但是当出现最多数字不止1个时,情况有变化
举个例子
1 1 1 1 2 2 2 2 3 4 5 6 7 8
由于1和2出现次数都最多,所以答案由1和2决定
这个时候,我们以1和2作为隔板
这样去构造1 2 (其他数) 1 2 (其他数) 1 2 (其他数) 1 2 (其他数)
1 2 (3 4) 1 2 (5 6) 1 2 (7 8) 2 6
所 以 设 出 现 次 数 最 多 的 数 出 现 了 x 次 , 有 n u m 个 数 出 现 了 x 次 所以设出现次数最多的数出现了x次,有num个数出现了x次 所以设出现次数最多的数出现了x次,有num个数出现了x次
答 案 是 ( n − n u m ∗ x ) / ( x − 1 ) + n u m − 1 答案是(n-num*x)/(x-1)+num-1 答案是(n−num∗x)/(x−1)+num−1
解释一下
n − n u m ∗ x n-num*x n−num∗x是出现次数不是最多数字的个数,这些数可以填充到隔板中间
也就是此时间隔了 ( n − n u m ∗ x ) / ( x − 1 ) (n-num*x)/(x-1) (n−num∗x)/(x−1)
至于怎么填充不用关心
因为总会有策略使得出现次数不是最多的数间隔大于出现次数最多的数
n u m − 1 num-1 num−1是隔板的贡献,比如上面例子隔板1 2长度是2
那么贡献是1,因为隔板1 2对1的贡献只有一个2而已
#include <bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
int t,n,a[maxn],vis[maxn];
int main()
{
cin >> t;
while( t-- )
{
cin >> n;
int num=0,maxx=0;
for(int i=1,x;i<=n;i++)
{
cin >> x;
maxx=max(maxx,++vis[x] );
}
for(int i=1;i<=n;i++)
{
if( vis[i]==maxx ) num++;
vis[i]=0;
}
cout<< (n-maxx*num)/(maxx-1)+num-1 << endl;
}
}