CF1227B题解

CF1227B题解

题意

给一个数组 \(q\),其中:

  • \(q_1=p_1\)
  • \(q_2=\max(p_1,p_2)\)
  • \(q_3=\max(p_1,p_2,p_3)\)
  • \(\cdots\)
  • \(q_n=\max(p_1,p_2,p_3,\cdots p_n)\)

求符合要求的 \(p\) 数组。

思路

有以下两点:

  1. 无解的情况:\(q[i]<i\),为啥呢?答:那是因为 \(q\) 数组的第 \(i\) 个是为 \(p\) 的前 \(i\) 个数中最大的。又因为 \(p\)\(1\sim n\) 中不重复的数字组成的数组。所以要是 \(q[i]<i\),就是无解。
  2. 求解操作呢,我借鉴了 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,\cdots n\),此时录入 \(q\),无解就不说了,我们要理解的是交换这一步,为啥是这样交换呢?分析如下:

我们都知道,\(q\) 数组的第 \(i\) 个是为 \(p\) 的前 \(i\) 个数中最大的,那么输入一个 \(q[i]\) 分为以下两种情况:

\(\begin{cases} q[i]=p[i]=\max(p[1],p[2],p[3],\cdots p[i])\\p[i]\neq\max(p[1],p[2],p[3],\cdots p[i]),q[i]=q[i-1] \end{cases}\)

对于第一种情况,\(p[i]\) 是没有被交换过的,所以 \(q[i]=p[i]=i\),所以交换了等于没交换。

对于第二种情况,因为 \(q[i]=q[i-1]\),所以就说明前面 \(p[q[i]]\) 已经交换过原来的小的了,在 \(p[q[i]]<p[i]<q[i]\),所以也不影响 \(q\) 数组最大值,操作合理。

总结

  1. 在做操作的时候记得赋初值。
  2. 记得特判无解的情况。
  3. 别忘了换行!

代码

#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;
}
posted @ 2025-01-29 15:27  naroto2022  阅读(11)  评论(0)    收藏  举报