当前位置:网站首页>2019浙江省赛C-错排问题,贪心
2019浙江省赛C-错排问题,贪心
2022-07-25 15:23:00 【塔子哥来了】
题目大意:
给你一个序列,让你找出一种字典序最小的错排。
题目思路:
1.将这个问题拓展一下:
给两个序列(不一定全等)。找字典序最小的错排。
2.错排存在的充要条件为:两个序列的和中出现次数最多的数 不超过 序列总长.(鸽巢定理)
3.依靠条件2,我们自然可以直接贪心的从小往大的填数,同时保证任意时刻,条件2成立即可(剩下的数最多出现次数不超过剩下的位置).
那么填数分两个阶段,第一个阶段贪心的填最小值和次小值。第二阶段到达条件2的临界条件。
代码有注释:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define vi vector<int>
#define vl vector<ll>
#define fi first
#define se second
const int maxn = 1e6 + 5;
const int mod = 1e9 + 7;
int a[maxn] , b[maxn] , n;
set<int> s;
multiset<int> ms; // 动态维护总出现次数
unordered_map<int,int> Tcnt , cnt; // 总体每个数出现次数和下面一列
void del (int x , int down){
auto g = ms.find(Tcnt[x]);
ms.erase(g);
Tcnt[x]--;
if (Tcnt[x] == 0) Tcnt.erase(x);
else ms.insert(Tcnt[x]);
if (down)
cnt[x]--;
if (cnt[x] == 0){
s.erase(x);
cnt.erase(x);
}
}
int c[maxn];
void imp (int x){
vi mx;
for (auto & g : Tcnt)
if (n - x + 1 == g.second) mx.push_back(g.first);
if (mx.size() == 1){
vi ot;
for (auto & g : cnt)
if (g.first != mx[0])
for (int i = 1 ; i <= g.second ; i++)
ot.push_back(g.first);
sort(ot.begin(),ot.end());
reverse(ot.begin(),ot.end());
for (int i = x ; i <= n ; i++){
if (a[i] == mx[0]) {
b[i] = ot.back();
ot.pop_back();
}else {
b[i] = mx[0];
}
}
}else {
// 真 唯一方案
for (int i = x ; i <= n ; i++){
if (a[i] == mx[0]) b[i] = mx[1];
else b[i] = mx[0];
}
}
return ;
}
int main()
{
ios::sync_with_stdio(false);
int t; cin >> t;
while (t--){
s.clear();
ms.clear();
Tcnt.clear();
cnt.clear();
cin >> n;
for (int i = 1 ; i <= n ; i++){
cin >> a[i];
s.insert(a[i]);
cnt[a[i]]++;
Tcnt[a[i]] += 2;
}
// 判断局面合法
bool ok = true;
for (auto & g : Tcnt){
if (g.second > n) {
ok = false;
break;
}
ms.insert(g.second);
}
if (!ok){
cout << "Impossible" << endl;
continue;
}
/* 放的时候有三种情况: 0.若 上下两行的数的并 最多出现次数 = 剩下位置的个数 ,这种局面直接处理 1.若当前对位不是最小值,就放最小值. 2.否则放次小值 要维护: 1.当前元素最小值,次小值 2.每个数出现次数以及出现次数的最大值 */
for (int i = 1 ; i <= n ; i++){
int mxcnt = *ms.rbegin();
if (mxcnt == n - i + 1){
imp(i);
break;
}
int miv[4], d = 0;
for (auto & g : s){
miv[++d] = g;
if (d == 2) break;
}
if (a[i] != miv[1]) b[i] = miv[1];
else b[i] = miv[2];
del(a[i] , false);
del(b[i] , true);
}
for (int i = 1 ; i <= n ; i++){
cout << b[i];
if (i == n) cout << endl;
else cout << " ";
}
}
return 0;
}
边栏推荐
猜你喜欢

Ml speech depth neural network model

Spark AQE

How much memory can a program use at most?

获取键盘按下的键位对应ask码

Yan required executor memory is above the max threshold (8192mb) of this cluster!

window系统黑窗口redis报错20Creating Server TCP listening socket *:6379: listen: Unknown error19-07-28

Spark SQL空值Null,NaN判断和处理

MATLAB 如何生产随机复序列

小波变换--dwt2 与wavedec2

matlab---错误使用 var 数据类型无效。第一个输入参数必须为单精度值或双精度值
随机推荐
No tracked branch configured for branch xxx or the branch doesn‘t exist. To make your branch trac
Solve the timeout of dbeaver SQL client connection Phoenix query
请问seata中mysql参数每个客户端连接最大的错误允许数量要怎么理解呢?
Spark提交参数--files的使用
异步fifo的实现
HBCK fix problem
Maxcompute SQL 的查询结果条数受限1W
在网页上实现任意格式的音视频快速播放功能的开发总结。
Single or multiple human posture estimation using openpose
redis淘汰策列
window系统黑窗口redis报错20Creating Server TCP listening socket *:6379: listen: Unknown error19-07-28
Idea护眼色设置
JVM-参数配置详解
ML - natural language processing - Basics
ML - 自然语言处理 - 关键技术
记一次Spark foreachPartition导致OOM
4PAM在高斯信道与瑞利信道下的基带仿真系统实验
Args parameter parsing
Spark SQL null value, Nan judgment and processing
期货在线开户是否安全?去哪家公司手续费最低?