资历太浅,没法给出什么高质量的内容(
本博客所记录的题目最低难度是 Div.2 的 C 题。
1.CF1768C. Elemental Decompress
显然,按照最大值从小到大排序之后会轻松很多。基本思路是这样,首先优先将第一个排列的值赋为最大值,然后选取第二个排列中能够使用的最小值。如果第一个排列中已经使用过当前位置上的最大值,就反过来执行一遍。如果一遍模拟下来不会有不合法的情况,就说明能够构造出方案,并直接输出构造的排列即可,否则输出 NO。
#include<bits/stdc++.h>
using namespace std;
struct node{
int val, id;
} a[200005];
int T, n;
bool v1[200005], v2[200005];
int a1[200005], a2[200005];
inline bool cmp(node x, node y) {return x.val < y.val;}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> T;
while(T--)
{
cin >> n;
for(int i = 1; i <= n; i++)
cin >> a[i].val, a[i].id = i;
sort(a + 1, a + n + 1, cmp);
int p1 = 1, p2 = 1;
for(int i = 1; i <= n; i++)
{
if(!v1[a[i].val]) v1[a[i].val] = 1, a1[a[i].id] = a[i].val, a2[a[i].id] = p2++;
else if(!v2[a[i].val]) v2[a[i].val] = 1, a1[a[i].id] = p1++, a2[a[i].id] = a[i].val;
else {cout << "NO\n"; goto end;}
if(a[i].val < p1 && a[i].val < p2) {cout << "NO\n"; goto end;}
while(v1[p1]) p1++;
while(v2[p2]) p2++;
}
cout << "YES\n";
for(int i = 1; i <= n; i++)
cout << a1[i] << ' ';
cout << '\n';
for(int i = 1; i <= n; i++)
cout << a2[i] << ' ';
cout << '\n';
end:;
for(int i = 1; i <= n; i++)
v1[i] = v2[i] = 0;
}
return 0;
}
2.CF1768D Lucky Permutation
一个很明显的性质是,这个逆序对一定是两个相邻的数所产生的,并且除了这两个数,第 \(i\) 个位置上的数就是 \(i\)。