Atcoder Grand Contest 014F - Strange Sorting

探讨一种特殊的排序算法,通过区分高值和低值元素并重新排列,直至完全有序。文章提供了算法实现思路及代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Problem Statement

Takahashi loves sorting.

He has a permutation (p1,p2,…,pN) of the integers from 1 through N. Now, he will repeat the following operation until the permutation becomes (1,2,…,N):

  • First, we will define high and low elements in the permutation, as follows. The i-th element in the permutation is high if the maximum element between the 1-st and i-th elements, inclusive, is the i-th element itself, and otherwise the i-th element is low.
  • Then, let a1,a2,…,ak be the values of the high elements, and b1,b2,…,bNk be the values of the low elements in the current permutation, in the order they appear in it.
  • Lastly, rearrange the permutation into (b1,b2,…,bNk,a1,a2,…,ak).

How many operations are necessary until the permutation is sorted?

Constraints

  • 1N2×105
  • (p1,p2,…,pN) is a permutation of the integers from 1 through N.

Input

Input is given from Standard Input in the following format:

N
p1 p2 ... pN

Output

Print the number of operations that are necessary until the permutation is sorted.


Sample Input 1

Copy
5
3 5 1 2 4

Sample Output 1

Copy
3

The initial permutation is (3,5,1,2,4), and each operation changes it as follows:

  • In the first operation, the 1-st and 2-nd elements are high, and the 3-rd, 4-th and 5-th are low. The permutation becomes: (1,2,4,3,5).
  • In the second operation, the 1-st, 2-nd, 3-rd and 5-th elements are high, and the 4-th is low. The permutation becomes: (3,1,2,4,5).
  • In the third operation, the 1-st, 4-th and 5-th elements are high, and the 2-nd and 3-rd and 5-th are low. The permutation becomes: (1,2,3,4,5).

Sample Input 2

Copy
5
5 4 3 2 1

Sample Output 2

Copy
4

Sample Input 3

Copy
10
2 10 5 7 3 6 4 9 8 1

Sample Output 3

Copy
6
题意:给一个排列,
 每次把max(a[1] to a[i]) = a[i]的放进vector A(记为high)里,其他放进vector B(记为low)里
然后把序列改成B + A
问升序排序需要搞多少次
题解:
我基本就是在翻译题解...

考虑去掉1剩下2到n的序列,剩下的答案是T,1并不影响其他数的操作
那么最后的答案一定是T或者T + 1
如果T = 0,直接判
如果T > 0,
考虑T - 1次操作之后的情况
记f为这个序列的第一项,显然f > 2
(如果f = 2,那么要么这个序列已经被排好序或者下一次f会被移到后面)
如果最后是(f, 1, 2)答案是T否则是T + 1

结论1:
(考虑序列2到n)
在前T - 1次, f不会出现它在不第一个位置且它又是high的情况
证明1:
考虑某个时刻x是high但是不在第一个位置, 显然第一个位置是high, 故vectorA中x前面还有一个数,记为y, y < x
如果x, y都是high或者都是low,它们的相对位置不变
如果x, y是high而y变成low了,这时y仍然在x左边,如果x不在第一个位置,和之前一样了

结论2:
定义循环序列(a, b, c) = (b, c, a) = (c, a, b)
则1, 2, f在前T - 1次组成的(关于它们位置的)循环序列不会变
证明2:
如果1是第一个元素
{
如果2是第二个元素,那么1, 2是high, f是low
如果f是第二个元素,那么1, f是high, 2是low
否则2, f都是low
}
如果2是第一个元素,那么2是high,1和f是low
如果f是第一个元素,那么f是high,1和2是low
否则1, 2, f都是low
然后就证明完了
#include <bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define fill( x, y ) memset( x, y, sizeof x )
#define copy( x, y ) memcpy( x, y, sizeof x )
using namespace std;

typedef long long LL;
typedef pair < int, int > pa;

inline int read()
{
	int sc = 0, f = 1; char ch = getchar();
	while( ch < '0' || ch > '9' ) { if( ch == '-' ) f = -1; ch = getchar(); }
	while( ch >= '0' && ch <= '9' ) sc = sc * 10 + ch - '0', ch = getchar();
	return sc * f;
}

const int MAXN = 200020;

int q[MAXN], p[MAXN], n, T[MAXN], f[MAXN];

int main()
{
#ifdef wxh010910
	freopen( "data.in", "r", stdin );
#endif
	n = read();
	for( int i = 1 ; i <= n ; i++ ) q[ p[ i ] = read() ] = i;
	for( int i = n - 1 ; i ; i-- )
	{
		if( !T[ i + 1 ] )
		{
			if( q[ i ] > q[ i + 1 ] ) T[ i ] = 1, f[ i ] = i + 1;
			else T[ i ] = 0;
		}
		else
		{
			int cnt = 0;
			cnt += q[ f[ i + 1 ] ] < q[ i ];
			cnt += q[ i ] < q[ i + 1 ];
			cnt += q[ i + 1 ] < q[ f[ i + 1 ] ];
			if( cnt == 2 ) T[ i ] = T[ i + 1 ], f[ i ] = f[ i + 1 ];
			else T[ i ] = T[ i + 1 ] + 1, f[ i ] = i + 1;
		}
	}
	return printf( "%d\n", T[ 1 ] ), 0;
}


评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值