当前位置: 代码迷 >> 综合 >> 沉鱼落雁(思维题)
  详细解决方案

沉鱼落雁(思维题)

热度:37   发布时间:2024-01-10 10:33:32.0

题目描述

胖头鱼在苦恼“沉鱼落雁”是什么好吃的东西,这很显然是因为他成语没背够。

于是他决定开始背成语。胖头鱼身为鱼界大佬,背成语的姿势自然也和常人不一:

他会先将所有要背的成语一字排开,比较难背的成语会重复出现,最多重复 3 次 (也就是出现次数可能为 1, 2 或 3)。这样就得到了一个可能有重复元素的成语序列,然后他会将这个序列打乱顺序,并按打乱后的顺序背下去。为了均匀的背所有成语,提高背成语的效率,相同成语在打乱后的序列中出现位置的最小间隔自然是越大越好。 (编号为 a 和 b (a<b) 的两个位置的间隔定义为 b?a?1)

现在胖头鱼把打乱前的成语序列给你,你需要帮他打乱顺序,使得相同成语的最小间隔最大。

你不需要输出确切的方案,仅求出最小间隔的最大值即可。

特别地,当每种成语都只出现一次时,把最小间隔的最大值视为n。

输入描述

第一行一个整数 n ( 1≤n≤10^5),表示成语序列长度为 n。同一个成语最在序列中最多出现 3 次。

接下来 n 个整数 a1, a2, …, an (1≤ai≤10^9) 表示一个成语序列,每个正整数都代表一个成语,两个成语不同当且仅当值不同。

输出描述

输出一个整数,表示最小间隔的最大值。

样例输入 1

9
5 4 3 1 3 1 1 5 5

样例输出 1

2

样例解释1

其中一組可行方案是1 3 5 1 3 5 1 4 5,容易验证没有比 22 更大的答案。

样例输入2

5
1 2 3 4 5

样例输出2

5
链接:

https://www.cometoj.com/contest/65/problem/B?problem_id=3683

解析:

思维题。

我们可以统计出现三次两次一次元素的个数,分别记为a,b,c;

假设11122233344556,我们可以发现有3个出现三次元素,2个出现两次的元素,1个出现一次的元素。我们可以这样 123 45 6 123 45 6 123这样分。

那么这时间隔为a-1+b+c/2,下取整。

如果没有出现三次的元素,例如112234

我们可以 12 3 4 12这样分

即 a+b-1

代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+20;
int a[maxn];
map<int, int> mp;
int main()
{
    ios::sync_with_stdio(false);int n;cin >> n;mp.clear();int count1,count2,count3;count1 = count2 = count3 = 0;for(int i = 0; i < n; i++) {
    cin >> a[i];mp[a[i]]++;}int mx = 0;for(auto u:mp) {
    if(u.second == 1)count3++;else if(u.second == 2)count2++;else if(u.second == 3)count1++;mx = max(mx, u.second);}if(mx == 1) {
    cout << n << endl;}else if(mx == 2){
    cout << count2 + count3 - 1 << endl;}else cout << count1 + count2 - 1 + (count3/2) << endl;return 0;
}

  相关解决方案