当前位置:网站首页>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;
}
边栏推荐
- Spark AQE
- C#精挑整理知识要点10 泛型(建议收藏)
- redis淘汰策列
- Iframe nested other website page full screen settings
- Remember that spark foreachpartition once led to oom
- VMware Workstation fails to start VMware authorization service when opening virtual machine
- Overview of JS synchronous, asynchronous, macro task and micro task
- args参数解析
- 记一次Spark报错:Failed to allocate a page (67108864 bytes), try again.
- In depth: micro and macro tasks
猜你喜欢

Spark submission parameters -- use of files

spark分区算子partitionBy、coalesce、repartition

盒子躲避鼠标

ML - natural language processing - Basics

ML - 图像 - 深度学习和卷积神经网络

Solve the timeout of dbeaver SQL client connection Phoenix query

How to solve the login problem after the 30 day experience period of visual stuido2019

BPSK调制系统MATLAB仿真实现(1)

matlab---错误使用 var 数据类型无效。第一个输入参数必须为单精度值或双精度值

VMware Workstation fails to start VMware authorization service when opening virtual machine
随机推荐
How to update JSON values in the database?
带你详细认识JS基础语法(建议收藏)
带你创建你的第一个C#程序(建议收藏)
延迟加载源码剖析:
Spark AQE
Vscode plugin collection
JVM parameter configuration details
C#精挑整理知识要点12 异常处理(建议收藏)
Remember that spark foreachpartition once led to oom
ML - 语音 - 传统语音模型
Once spark reported an error: failed to allocate a page (67108864 bytes), try again
Graph theory and concept
wait()和sleep()的区别理解
How spark gets columns in dataframe --column, $, column, apply
Spark SQL common time functions
spark分区算子partitionBy、coalesce、repartition
Endnote 无法编辑range 解决
Spark DF adds a column
解决DBeaver SQL Client 连接phoenix查询超时
ML - 自然语言处理 - 自然语言处理简介