Codeforces Round #842 (Div. 2)
Codeforces Round #842 (Div. 2)
https://codeforces.com/contest/1768
A. Greatest Convex
猜结论
#include <bits/stdc++.h>
using namespace std;
void solve () {
int n;
cin >> n;
cout << n - 1 << endl;
}
int main () {
int t;
cin >> t;
while (t --) solve ();
}
B. Quick Sort
想了好久。
记录从1出发的最长上升序列长度 \(len\)(值中断就要断掉),答案就是 \((n-len+k-1)/k\)
因为把除了这一段之外的其它数字排好之后,这一段就会自动有序。
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int a[N], n, k;
void solve () {
int ans = 0, pos = 0, len = 1;
cin >> n >> k;
for (int i = 1; i <= n; i++) {
cin >> a[i];
if (a[i] == 1) pos = i;
}
for (int i = pos + 1, k = 2; i <= n; i++) {
if (a[i] == k) len ++, k++;
}
//cout << cnt << ' ';
cout << (n - len + k - 1) / k << endl;
}
int main () {
int t;
cin >> t;
while (t --) solve ();
}
//最长有序序列
C. Elemental Decompress
贪心。
贪心从小往大放。如果当前数字只出现一次,就可以让 \(p,q\) 都等于这个数字;如果当前数字出现两次,则一个放该数字,另一个放她对应的 \(set\) 里面最小值( \(set\) 里面存的是这个数组还没放的值)。看代码就很好懂啦!
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
const int N = 2e5 + 5;
int cnt[N], p[N], q[N], n;
pii a[N];
void solve () {
cin >> n;
set<int> s1, s2;
for (int i = 1; i <= n; i++) cnt[i] = 0, s1.insert (i), s2.insert (i);
for (int i = 1; i <= n; i++) {
int x; cin >> x;
a[i] = {x, i};
cnt[x] ++;
}
for (int i = 1; i <= n; i++) {
if (cnt[i] > 2) {
puts ("NO");
return ;
}
}
sort (a + 1, a + n + 1);
for (int i = 1; i <= n; i++) {
int val = a[i].first, pos = a[i].second;
if (cnt[val] != 2) {
p[pos] = q[pos] = val;
s1.erase (val), s2.erase (val);
}
else {
if (s1.count (val)) {
if (*s2.begin () > val) {
puts ("NO");
return ;
}
p[pos] = val, q[pos] = *s2.begin ();
s1.erase (val), s2.erase (s2.begin ());
}
else {
if (*s1.begin () > val) {
puts ("NO");
return ;
}
q[pos] = val, p[pos] = *s1.begin ();
s2.erase (val), s1.erase (s1.begin ());
}
}
}
puts ("YES");
for (int i = 1; i <= n; i++) cout << p[i] << ' '; cout << endl;
for (int i = 1; i <= n; i++) cout << q[i] << ' '; cout << endl;
}
int main () {
int t;
cin >> t;
while (t --) solve ();
}
//从小往大放
D. Lucky Permutation
结论题。
置换环结论: \(cnt\) 个环,变成排列所需次数为 \(n-cnt\),具体可以看 \(ygg\) 的题姐。
有序排列 \(\rightarrow\) 一个逆序对: 交换任意邻项 (本来需要 \(n-cnt+1\) 次,如果环中存在邻项的话就可以节省两次)
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
int a[N], n, cnt;
bool vis[N], exist;
set<int> s;
void dfs (int x) {
if (vis[x]) return ;
vis[x] = true;
s.insert (x);
if (s.count (x - 1) || s.count (x + 1)) exist = true;
dfs (a[x]);
}
void solve () {
cin >> n;
cnt = 0, exist = false;
for (int i = 1; i <= n; i++) cin >> a[i], vis[i] = false;
for (int i = 1; i <= n; i++) {
if (vis[i]) continue;
cnt ++, s.clear ();
dfs (i);
}
int ans = n - cnt + 1;
if (exist) ans -= 2;
cout << ans << endl;
}
int main () {
int t;
cin >> t;
while (t --) solve ();
}
//置换环结论: cnt个环,变成排列所需次数为n-cnt
//有序排列->一个逆序对: 交换任意邻项(本来是n-cnt+1,如果环中存在邻项的话就可以节省两次)