Codeforces Round #662 (Div. 2) C. Pinkie Pie Eats Patty-cakes (思维,分块)

题目传送
题意:
给你n个数,问你相邻俩个相同的数的最大最小距离是多少

思路:
我为什么写了个分块在标题上面呢?

例:有数 1 1 1 2 2 2 3 3 3 4 4 5 6
那么我们是如何分呢?
1.我的方法是先统计相同的数的最多出现的次数(Max),和拥有相同Max的数的个数(sum)。

2.这里Max = 3,sum = 3,那么我们肯定要使得这些数尽量的错开,也就是1 2 3 1 2 3 1 2 3这种错开(我称为把1 2 3 作为一块)

3.这样做可以使得相同的数距离的最远,那么我们发现还有4 4 5 6呢?我们就要把这些数插到上面分的块之间,使得距离再远一点,但是我们也注意到了,还有4 4这俩个数,那么我们也要同时把他们错开,那么俩个4的距离会不会比上面所分的快的距离还近呢?答案是不会的,你可以观察一下,我们随便怎么插,如: 1 2 3 4 丨1 2 3 4 丨 1 2 3,这种,最近的时候也才和拥有Max的数的距离相等,所以不必考虑这个问题。

4.所以我们把分块后剩下的数插入到块之间的空隙中,并且尽可能的每一个间隙插入的平均(使得距离更大),上述例子: 1 2 3 4 丨 1 2 3 4 6 丨 1 2 3 5 ,为什么说平均呢?就比如这个6就是无效的,摆在哪个位置都可以

那么我们怎么算平均呢?
n - Max*sum (剩下的数) / (Max - 1) (块之间的间隙多少)

AC代码

#include <bits/stdc++.h>
inline int read(){char c = getchar();int x = 0,s = 1;
while(c < '0' || c > '9') {if(c == '-') s = -1;c = getchar();}
while(c >= '0' && c <= '9') {x = x*10 + c -'0';c = getchar();}
return x*s;}
using namespace std;
#define NewNode (TreeNode *)malloc(sizeof(TreeNode))
#define Mem(a,b) memset(a,b,sizeof(a))
#define lowbit(x) (x)&(-x)
const int N = 1e5 + 5;
const long long INFINF = 0x7f7f7f7f7f7f7f;
const int INF = 0x3f3f3f3f;
const double EPS = 1e-7;
const int mod = 1e9 + 7;
const double II = acos(-1);
const double PP = (II*1.0)/(180.00);
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<ll,ll> piil;
signed main()
{
    std::ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    //    freopen("input.txt","r",stdin);
    //    freopen("output.txt","w",stdout);
    int t,n;
    cin >> t;
    while(t--)
    {
        cin >> n;
        int vis[n+10] = {0};
        for(int i = 0,num;i < n;i++)
        {
            cin >> num;
            vis[num]++;
        }
        sort(vis,vis+n+5,greater<int>());//从大到小排序
        int Max = vis[0],sum = 0;//记录最大值,和数量
        for(int i = 0;i <= n;i++)
        {
            if(Max != vis[i]) break;
            sum++;
        }
        cout << (sum - 1 + (n - sum*Max)/(Max - 1)) << endl;//计算公式 sum -1 是分块时,还没插入数的时候本来就有的最大距离
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值