AGC014-F Strange Sorting

题意

\(n\)-排列,反复进行:将序列中为前缀最大值的数全部移动到序列末(两种数不改变相对位置),问经过多少次后第一次全部升序排列

做法

定义:用high表示为前缀最大值,low则反之
考虑忽略\(1\),那么\([2,n]\)相对排好序后,假设用了\(T\)次,如果\(1\)在首,则答案为\(T\),否则还要在进行一次,为\(T+1\)

检查答案是\(T\)还是\(T + 1\)\(T = 0\)的情况非常简单
假设\(T> 0\),并考虑\(T − 1\)运算后序列的状态
\(f\)为在\(T-1\)运算之后,在\([2,n]\)在序列中首先出现的整数。通过\(T\)的定义,我们可以证明\(f> 2\)(否则,要么\([2,n]\)\(T-1\)运算中排序,要么再操作一下也排不好)。可以看到,在\(T − 1\)次后,如果\(1\)出现在\(f\)\(2\)之间,则答案为\(T\),否则为\(T + 1\)

结论1\(f\)不会出现其不在第一个位置且为high的情况

证明:考虑反证
第一个数\(y\)为high,\(y<f\)
当它们同时为high或low,相对位置不变
否则只可能\(y=low,f=high\),相对位置还是不变

结论2
定义循环序列\((a, b, c) = (b, c, a) = (c, a, b)\)
\(1, 2, f\)在前\(T - 1\)次组成的(关于它们位置的)循环序列不会变

证明:
\((1)\)如果\(1\)是第一个元素(这里指的不是相对顺序,就是指排在序列首)
\(~~~(i)\)如果\(2\)是第二个元素,那么\(1, 2\)是high, f是low
\(~~~(ii)\)如果\(f\)是第二个元素,那么\(1, f\)是high, 2是low
\(~~~(iii)\)否则2, f都是low
\((2)\)如果\(2\)是第一个元素,那么\(2\)是high,\(1\)\(f\)是low
\((3)\)如果\(f\)是第一个元素,那么f是high,\(1\)\(2\)是low
\((4)\)否则\(1, 2, f\)都是low

考虑\([i,n]\),令\(T_i\)为对序列进行排序所需的操作数。
\(f_i\)\(T_i − 1\)次操作后的第一个整数,考虑整数\([i,n]\)。(如果\(T_i = 0\)\(f_i\)是不确定的)。
\(q_i\)\(i\)在初始序列中的位置(即\(p_{q_i}= i\))。然后,我们按\(i = N,N − 1…1\)的顺序计算值\(T_i,f_i\),答案为\(T_1\)。当\(i <N\)时,可以按以下方式计算值:

  • 如果\(T_{i + 1} = 0\)
    \((1)\)如果\(q_i> q_{i + 1}\),则\(T_i = 1\)\(f_i = i + 1\)
    \((2)\)否则,\(T_i = 0\)\(f_i\)未定义。
  • 除此以外,
    \((1)\)如果\(q_{f_{i + 1}}\)\(q_i\)\(q_{i+1}\)处于此循环顺序,则\(T_i = T_{i + 1}\)\(f_i = f_{i +1}\)
    \((2)\)否则,\(T_i = T_{i + 1} +1\)\(f_i = i + 1\)

题外话

题解的搬运工...

code(wxh)

#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;
}

posted @ 2020-02-25 10:59  Grice  阅读(220)  评论(0编辑  收藏  举报