CF1227B题解
CF1227B题解
题意
给一个数组 q,其中:
- q1=p1。
- q2=max(p1,p2)。
- q3=max(p1,p2,p3)。
- ⋯
- qn=max(p1,p2,p3,⋯pn)
求符合要求的 p 数组。
思路
有以下两点:
- 无解的情况:q[i]<i,为啥呢?答:那是因为 q 数组的第 i 个是为 p 的前 i 个数中最大的。又因为 p 为 1∼n 中不重复的数字组成的数组。所以要是 q[i]<i,就是无解。
- 求解操作呢,我借鉴了 SunArrebol 这位大佬,但是他没有解释,首先先讲解法:
bool ok=0;//记录是否有符合题意的p数组
for(int i=1; i<=n; i++) p[i]=i;
for(int i=1; i<=n; i++){
scanf("%d",&q[i]);
if(q[i]<i) ok=1;//标记为无解。
else swap(p[i],p[q[i]]);//交换
}
那为啥是上面那样呢?首先一开始已经赋值 p 为 1,2,3,⋯n,此时录入 q,无解就不说了,我们要理解的是交换这一步,为啥是这样交换呢?分析如下:
我们都知道,q 数组的第 i 个是为 p 的前 i 个数中最大的,那么输入一个 q[i] 分为以下两种情况:
{q[i]=p[i]=max(p[1],p[2],p[3],⋯p[i])p[i]≠max(p[1],p[2],p[3],⋯p[i]),q[i]=q[i−1]
对于第一种情况,p[i] 是没有被交换过的,所以 q[i]=p[i]=i,所以交换了等于没交换。
对于第二种情况,因为 q[i]=q[i−1],所以就说明前面 p[q[i]] 已经交换过原来的小的了,在 p[q[i]]<p[i]<q[i],所以也不影响 q 数组最大值,操作合理。
总结
- 在做操作的时候记得赋初值。
- 记得特判无解的情况。
- 别忘了换行!
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int p[100005],q[100005],T,n;
int main(){
scanf("%d",&T);
while(T--){//有T组数据
scanf("%d",&n);
bool ok=0;//记录是否有符合题意的p数组
for(int i=1; i<=n; i++) p[i]=i;//赋初值
for(int i=1; i<=n; i++){
scanf("%d",&q[i]);
if(q[i]<i) ok=1;//标记为无解。
//为啥无解呢?
//那是因为:q数组的第i个是为p的前i个数中最大的。
//又因为p为1~n中不重复的数字组成的数组。
//所以要是q[i]<i,就是无解。
else swap(p[i],p[q[i]]);//交换
}
if(ok==1) printf("-1");//无解
else for(int i=1; i<=n; i++) printf("%d ",p[i]);
printf("\n");//记得换行
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现