题目
t(t<=1e4)组样例,
每次给定一个数n(n<=2e5),代表有n个魔方,第i个魔方的颜色是ai(1<=ai<=n)
n个魔方需要放在m(m<=n)个架子上,使得第j个架子上恰好放了sj个魔方(sum sj=n)
第i个架子的彩色度,定义为最近的两个颜色相同的魔方之间的距离,
如果第i个架子上不存在两个颜色相同的魔方,则彩色度为架子上魔方的个数,即si
第i个架子有一个限制di(1<=di<=si),要求彩色度最低不得低于di
输出m个架子构造的魔方序列,
如果不存在合法序列,输出-1
思路来源
潼神b站讲解
题解
似乎很难证这样的正确性,但可以感性理解一下,这样做不会比其他更劣
做法是,先将魔方统计每种颜色出现的个数,
维护一个set,set按出现次数从多到少排序,多的在前面
对于每个架子si,彩色度的最小限制di,意味着,每di个数都两两不同,
即将架子划分成了若干个长度为di的区间(最后一个区间可能小于di)
那么,每个区间内填的这di个数,是从set里取的出现次数最多的di种数,
如果set内数的种类数不足di,则输出无解
填完之后,对于每种数的出现次数减1,然后如果还剩有次数,就放回set
首先,这样肯定能保证两个相同的数的距离>=di,
因为考虑第x段的数v和第x+1段的数v之间的数,
出现在第x段的数,一定不为v,
出现在第x+1段v前面的数,其出现次数大于等于v的出现次数,
v没有用完,则这些数也没有用完,
所以本次的偏移量只会等于上次的偏移量,为di
其实我感觉,按si从大到小排序,会显得更贪心一些,
因为颜色种类数一开始有很多,后面就变少了
不太好举反例,而且潼神是按输入的si顺序操作的,也通过了,就姑且这样吧
代码
// Problem: D. Colorful Constructive
// Contest: Codeforces - Codeforces Round 908 (Div. 1)
// URL: https://codeforces.com/contest/1893/problem/D
// Memory Limit: 512 MB
// Time Limit: 3000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define pb emplace_back
struct St{
int cnt, num;
bool operator <(const St &b) const{
if (cnt != b.cnt) return cnt > b.cnt;
return num < b.num;
}
};
int cnt[200005];
int a[200005], b[200005];
vector<St> ans[200005];
void solve(){
int n, m; cin >> n >> m;
for (int i = 1; i <= n; i++) cnt[i] = 0, ans[i].clear();
for (int i = 1; i <= n; i++){
int x; cin >> x;
cnt[x]++;
}
set<St> s;
for (int i = 1; i <= n; i++){
if (cnt[i]){
s.insert({cnt[i], i});
}
}
for (int i = 1; i <= m; i++) cin >> a[i];
for (int i = 1; i <= m; i++) cin >> b[i];
for (int i = 1; i <= m; i++){
while (a[i] > 0){
int t = min(a[i], b[i]);
a[i] -= t;
if (s.size() < t){
cout << -1 << '\n';
return;
}
int cnt = 0;
for (auto j : s){
ans[i].pb(j);
cnt++;
if (cnt == t) break;
}
for (auto j : ans[i]){
s.erase(j);
if (j.cnt > 1) s.insert({j.cnt - 1, j.num});
}
}
}
for (int i = 1; i <= m; i++){
for (auto j : ans[i]) cout << j.num << ' ';
cout << '\n';
}
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
int T; cin >> T;
while (T--){
solve();
}
}