【Codeforces Round #662 (Div. 2) 】C. Pinkie Pie Eats Patty-cakes 貪心
阿新 • • 發佈:2020-09-16
題意
給出 \(n\) 個數字,每個數字都大於等於 1,小於等於 n。現在問怎麼排列使得任意兩個相同的數字之間的最小距離最大。
思路
看完就直接想到了二分,二分最小距離。
關鍵就在check
函式怎麼寫?
首先按照出現次數從大到小排序,優先處理出現次數多的。
依次遍歷數字,對於當前數字,找到第一個可以放的位置,然後該位置 +=x(x是當前檢驗的最小距離),即接下來這個數字可以放的位置,如果新得到的位置已經有數字,那麼向後遍歷找到第一個沒有數字的位置。
如果該數字沒有放完,並且此時可以放的下標已經超過 n 了,那麼當前距離就不合法。
但是 WA 了。
比如這個樣例:
1 10 1 1 2 2 3 3 4 4 4 4
在檢驗 x 為 2 的時候,會形成下面的排列:
4 1 4 1 4 2 4 2 3 3
這是不合法的。最後會輸出0。
但是可以這樣排列:4 3 2 4 3 1 4 2 1 4
,答案應該是2。
然後二分我想不到怎麼放了。
看著樣例突然想到了模擬:
我們按照最大的出現次數分組,每組最初都有一個最大出現次數的數字。
比如上面的樣例,有4 個 4,那麼我們分成 4 組,。
①:4
②:4
③:4
④:4
接下來我們按照出現次數從高到低的數字往每個組裡放數字:1 2 3。
①:4,1,2
②:4,1,3
③:4,2,3
④:4
答案就是 2。
這裡產生一個問題,也就是最後一組到底要不要放數字?
乍一看不放數字是最好的,但是會出問題,比如:
2 2 2 1 1 1 3 3 3
如果不放會變成如下這樣:
①:1,2,2,3
②:1,2,3,3
③:1,
這樣排列相同的就直接在一起了。
原因就是有多個出現次數相同的,那麼可以這樣放:如果該數字的出現次數和最大次數相同,那麼最後一組就應該放,否則最後一組不放。
此時答案為長度最短的一個組的長度 - 1。
程式碼
/* * @Autor: valk * @Date: 2020-04-04 14:56:12 * @LastEditTime: 2020-09-16 19:47:11 * @Description: 如果邪惡 是華麗殘酷的樂章 它的終場 我會親手寫上 晨曦的光 風乾最後一行憂傷 黑色的墨 染上安詳 */ #include <bits/stdc++.h> #define fuck system("pause") #define emplace_back push_back #define pb push_back using namespace std; typedef long long ll; typedef unsigned long long ull; const int mod = 1e9 + 7; const int seed = 12289; const double eps = 1e-6; const int inf = 0x3f3f3f3f; const int N = 2e5 + 10; int arr[N], cnt[N]; int main() { int _; scanf("%d", &_); while (_--) { memset(cnt, 0, sizeof(cnt)); int n; scanf("%d", &n); int maxn = -1, num = -1; for (int i = 1; i <= n; i++) { scanf("%d", &arr[i]); cnt[arr[i]]++; maxn = max(maxn, cnt[arr[i]]); } int rel = n; for (int i = 1; i <= n; i++) { if (cnt[arr[i]] == maxn) { rel--; } } sort(arr + 1, arr + 1 + n); n = unique(arr + 1, arr + 1 + n) - arr - 1; for (int i = 1; i <= n; i++) { if (cnt[arr[i]] == maxn) { num++; } } printf("%d\n", num + rel / (maxn - 1)); } return 0; } /* 1 10 1 1 2 2 3 3 4 4 4 4 4 7 1 7 1 6 4 4 6 */