CF1973C Cat, Fox and Double Maximum
题目传送门
题面
给你一个长度为的排列,保证为偶数,你需要构造另一个长度为的排列,将两个排列每一位相加得到一个新数列,你要使得这个新数列的极大值最多。
极大值即某个数严格大于他相邻的两个数,位于边界的数字无法成为极大值。
题解
这题是在猜测答案是上界 的前提下完成构造的,做法略巧。
如图,红色部分是给定的排列,我们考虑先把它填平至, 即黑线,此时用于填平的蓝色部分也构成一个排列。
我们考虑通过交换蓝色方块,来使得数列满足所有偶数位置严格大于n+1, 所有奇数位置都小于等于, 此时达到上界。注意我们不能确定是否存在一种这样的构造方法,但恰巧是有的而且我们想到了,这有很大部分的运气成分。
交换方法是这样的:
因为我们要让所有偶数位置增加,奇数位置减小或者不变,所以每一个偶数位置的蓝色块要换成一个比它更大的蓝色块,我们不妨直接换成比现在蓝色块刚好大1的蓝色块,比如现在有一个蓝色块3在偶数位置,我们考虑将他和4换,若4在奇数位置,则可以直接换,若4在偶数位置,则将4放在3的位置,5放在4的位置, 若5在奇数位置,则将3放在5的位置就好,若5依然为偶数位置,则将6放在5,如此继续直到出现一个在奇数位置的数。
如图,7在奇数位置减小,而其他位置均增大。
问题来了,是否会一直换到都在偶数位置呢?
很简单,若为偶数位,则让所有奇数位为极大值,否则则让所有偶数为极大值,这样就可以保证做法正确。
实现
const int N = 1e6;
int a[N], pos[N];
int ans[N];
int T, ch, n;
int main(){
T = read();
while(T--){
n = read();
for(int i=1; i<=n; i++)
a[i] = read();
for(int i=1; i<=n; i++){
pos[n+1-a[i]] = i;
}
ch = pos[n]%2;
ans[pos[n]] = n;
for(int i=1; i<n; ){
if(pos[i]%2 == ch) {
ans[pos[i]] = i;
i++;
continue;
}
int j = i+1;
while(pos[j]%2 != ch) j++;
for(int k=i; k<j; k++){
ans[pos[k]] = k+1;
}
ans[pos[j]] = i;
i = j + 1;
}
for(int i=1; i<=n; i++) printf("%d ", ans[i]);
printf("\n");
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】