AGC014-F Strange Sorting

Posted grice

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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
", T[ 1 ] ), 0;
}

以上是关于AGC014-F Strange Sorting的主要内容,如果未能解决你的问题,请参考以下文章

学习笔记[AGC044C] Strange Dance

UVA10519 Really Strange大数+递推

国赛 strange_int

ruby sidetiq_strange.rb

leetcode 664. Strange Printer

AtCoder - 3939 Strange Nim