思路:
最少要多少个包裹既是某个数出现的最多次。
接下来才是重头戏,怎么输出序列呢?
我第一次的做法是用优先队列一次次慢慢输出,虽然结果正确,但代码冗长。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef vector<vi> vii;
typedef vector<ll> vll;
const int MAXN = 1e6 + 10;
const ll INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
const double eps = 1e-8;
int n, m, k;
vi p;
map<int, int> mp;
typedef struct Node{
int v, t;
Node(int a, int b){
v = a;
t = b;
}
bool operator < (const Node &rhs) const{
if(t == rhs.t)
return v > rhs.v;
return t < rhs.t;
}
}Node;
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
cout << setprecision(10) << fixed;
while(cin >> n, n){
p.clear();
p.resize(n);
for(int i = 0; i < n; i++)
cin >> p[i];
sort(p.begin(), p.end());
if(mp.size())
cout << endl;
int res = 0;
mp.clear();
for(int i = 0; i < n; i++){
mp[p[i]]++;
res = max(res, mp[p[i]]);
}
cout << res << endl;
priority_queue<Node> q;
queue<Node> buf;
for(auto it = mp.begin(); it != mp.end(); ++it)
q.push(Node(it ->first, it ->second));
vi num;
num.resize(res);
for(int i = 0; i < res; i++)
num[i] = n / res + (i + 1 <= n % res);
for(int i = 0; i < res; i++){
while(!buf.empty()){
q.push(buf.front());
buf.pop();
}
vi save;
for(int j = 0; j < num[i]; j++){
save.push_back(q.top().v);
if(q.top().t - 1)
buf.push(Node(q.top().v, q.top().t - 1));
q.pop();
}
sort(save.begin(), save.end());
for(int j = 0; j < (int)save.size(); j++){
if(j)
cout << " ";
cout << save[j];
}
cout << endl;
}
}
cerr << "execute time : " << (double)clock() / CLOCKS_PER_SEC << endl;
return 0;
}
第二次就聪明了,因为输出的序列总数和出现最多次的数的次数是一样的,所以这样做就可以了。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef vector<vi> vii;
typedef vector<ll> vll;
const int MAXN = 1e6 + 10;
const ll INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
const double eps = 1e-8;
int n, m, k;
map<int, int> mp;
vi p;
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
cout << setprecision(10) << fixed;
while(cin >> n, n){
p.clear();
p.resize(n);
for(int i = 0; i < n; i++)
cin >> p[i];
sort(p.begin(), p.end());
if(mp.size())
cout << endl;
mp.clear();
int res = 0;
for(int i = 0; i < n; i++)
res = max(res, ++mp[p[i]]);
cout << res << endl;
for(int i = 0; i < res; i++){
cout << p[i];
for(int j = i + res; j < n; j += res)
cout << " " << p[j];
cout << endl;
}
}
cerr << "execute time : " << (double)clock() / CLOCKS_PER_SEC << endl;
return 0;
}
因为这n段序列一定每段都包含出现最多次的数。
未来可期。