题解:CF1973C Cat, Fox and Double Maximum
题意简述
给定长度为 \(n\) 的排列 \(p\),构造另一长度为 \(n\) 的排列 \(q\),使得新序列 \(a\) \((a_i = p_i + q_i)\) 有最多的局部最大值,求任意 \(q\)。
局部最大值是指对于一个位置 \(i (1 \lt i \lt n)\),\(a_i \gt a_{i-1}\) 且 \(a_i \gt a_{i+1}\)。
题目分析
思路过程
由于局部最大值严格大于两边,所以 \(a\) 序列中相邻两个数不可能都是局部最大值,那么,长为 \(n\) 的 \(a\) 序列中最多有 \(\frac{n}{2}\) 个局部最大值。
由于 \(p\) 和 \(q\) 都是长度为 \(n\) 的排列,所以将 \(p\) 设为 \(p = \{1, 2, \dots , n\}\),将 \(q\) 设为 \(q = \{n, n - 1, \dots , 1\}\) 后,\(a\) 序列的每个数都为 \(n + 1\)。
考虑在这个基础之上构造,使 \(a\) 序列的偶数位都增加 \(1\),这样成功构造了有 \(\frac{n}{2}\) 个局部最大值的序列。那么对应的 \(q\) 的偶数位都要加 \(1\),(若 \(q\) 的偶数位上有 \(n\) 这个数,我们考虑在奇数位上构造,避免越界),这时,我们不再能保证 \(q\) 是个排列,\(q\) 的某些位可能会重复。原因就是被加 \(1\) 的偶数位占了位置,而它们本来的位置空了出来。我们考虑将被占奇数位调整到空位上,即可完成对 \(q\) 的构造。
对奇数位的构造也类似,这里只解释偶数位了。
实现与证明
具体实现上,先算出 \(q\) 的初始状态,然后考虑先让 \(q\) 中偶数位改变后的值占位,用 vis 打标记。之后将 \(q\) 的奇数位放入 vector 中排序,从小到大地枚举 vector 中的数,若本来的位置没被占,就可以直接打标记占领这个位置;若被占,则寻找目前没被占领的最小数去占领,并改动对应的 \(q\) 中的值。
为什么从小到大排序配位置正确?
考虑对被占位的奇数位的数字 \(x\),\(x - 1\) 可能空了出来,若还是被占位,\(x - 2\) 可能空了…… 所以每个被占位的数,总会有一个比它小的数留给它,从小到大枚举奇数位的数,找到的替代位必然小于这个数,所以 \(a\) 序列奇数位这些不该变大的位不会变大,只会变小,满足题意。
\(Code\)
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
using namespace std;
const int NR = 1e5 + 10;
int p[NR], q[NR];
int vis[NR], pos[NR];
vector<int> v;
int main()
{
int T;
scanf("%d", &T);
while (T --)
{
memset(vis, 0, sizeof(vis));
v.clear();
int n;
scanf("%d", &n);
int flag = 0; // 判断偶数位是否有 n 而导致 q 数组越界
for (int i = 1; i <= n; i ++)
{
scanf("%d", &p[i]);
q[i] = n + 1 - p[i];
if (i % 2 == 0 && q[i] == n) flag = 1;
}
// 需要 +1 做贡献的位
for (int i = 2 - flag; i <= n; i += 2)
{
q[i] ++;
vis[q[i]] ++;
}
// 其余(可能)需要调整的位
for (int i = 1 + flag; i <= n; i += 2)
{
v.push_back(q[i]);
pos[q[i]] = i;
}
sort(v.begin(), v.end());
int avb = 1; // 不断用来查找从 1 开始可用的位,相当于指针
for (int i = 0; i < (int)v.size(); i ++)
{
if (vis[v[i]])
{
// 这个位置已经被占,需要调整
while (vis[avb]) avb ++;
q[pos[v[i]]] = avb;
vis[avb] = 1;
}
else
{
// 这个位置没有被占,占领这里
vis[v[i]] = 1;
}
}
for (int i = 1; i <= n; i ++)
{
printf("%d ", q[i]);
}
puts("");
}
return 0;
}

浙公网安备 33010602011771号