专栏文章

题解:P13492 【MX-X14-T2】反转时光

P13492题解参与者 6已保存评论 6

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
6 条
当前快照
1 份
快照标识符
@miopqvld
此快照首次捕获于
2025/12/02 23:08
3 个月前
此快照最后确认于
2025/12/02 23:08
3 个月前
查看原文
前言:这道题目的数据真的很水。

进入正题:

一.我们怎么确定这道题是什么算法?

我们可以先看 100%100\% 的数据:
对于 100%100\% 的数据,1n1051 \le n \le 10^{5} ,保证 pp 是一个 1n1 \sim n 的排列。
由此,我们可知暴力是会超时的,通过此题要用 O(n)O(n)O(nlogn)O(n \log n) 的做法,考虑数学或二分。但这道题不满足使用二分的单调性,所以这道题我们使用数学。

二.如何得出规律?

我们可以针对样例:
对于样例一的解释:这明显是一个连续上升的序列,不用交换,所以 kk11。同样的,只要序列满足连续上升,则 kk11
对于样例二的解释:这个序列有两个依次上升的子序列,我们可以交换这两个子序列,使它变得有序,所以 kk 的值为 22。同样的,序列只要满足有两个依次上升的子序列,我们的 kk 就等于 22。(注:这两个序列一定是依次上升的,否则就不能输出 22。)
对于样例三的解释:对于这个完全无序的序列,我们可以输出 33,可以证明 33 是最小的 kk,我们只需要每次将最大值、次大值、次次大值......依次找出来,将它的左边变成序列一,本身变成序列二,右边变成序列三,将序列一和序列二交换,就可以将最大值、次大值、次次大值......依次放在序列的左边,也就是说,对于一个长度为 nn 的完全无序的序列,最多进行 nn 次操作,就可以将它变成一个有序的序列,以下是例子:
对于序列:33224411,我们可以很容易发现它是完全无序的,我们可以做出以下操作:
  1. 交换 332244 得序列 44332211
  2. 交换 4433 得序列 33442211
  3. 交换 334422 得序列 22334411
  4. 交换 22334411 得序列 11223344
综上,我们的 kk 最小是 33

三.代码

CPP
#include<bits/stdc++.h>
using namespace std;
int n,a[100005],l;
bool check(int r){//判断 k 是否是 1 或 2。
	for(int i=r;i<n;i++){
		if(a[i]!=a[i+1]-1){
			return 0;
		}
	}
	for(int i=1;i<r-1;i++){
		if(a[i]!=a[i+1]-1){
			return 0;
		}
	}
  //以上是遍历序列,看看它是否满足样例二的格式。
	return 1;//满足返回 1。
}
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		if(a[i]==1){
			l=i;//记录 1 的位置,遍历的时候有一个起始点。
		}
	}
	if(check(l)&&l==1){//特判,如果它是样例一的格式,输出 1。
		cout<<1;
	}
	else if(check(l)){//否则如果它满足有两个依次上升的子序列,输出 2。
		cout<<2;
	}
	else{//如果它是完全无序的序列,输出 3。
		cout<<3;
	}
	return 0;
}

评论

6 条评论,欢迎与作者交流。

正在加载评论...