题意

\(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;
}

AGC014-F Strange Sorting的更多相关文章

  1. C Strange Sorting

    C. Strange Sorting time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

  2. 数论F - Strange Way to Express Integers(不互素的的中国剩余定理)

    F - Strange Way to Express Integers Time Limit:1000MS     Memory Limit:131072KB     64bit IO Format: ...

  3. agc014F Strange Sorting

    这套题比较简单,以为自己能够独立A掉D和E,或许就能自己A掉F,看来还真是想多了 题意:给一个$n$的全排列,每次操作把$max(a[1],a[2],...,a[i]) = a[i]$的记为$high ...

  4. 2020CCPC长春F. Strange Memory

    题目大意 一棵以 \(1\) 为根的 \(n(2\leq n\leq 10^5)\) 的树,每个节点 \(i\) 有权值 \(a_{i}(1\leq a_{i}\leq 10^6)\) ,求 \(\s ...

  5. codeforces 484C Strange Sorting Codeforces Round #276 (Div. 1) C

    思路:首先 他是对1到k 元素做一次变换,然后对2到k+1个元素做一次变化....依次做完. 如果我们对1到k个元素做完一次变换后,把整个数组循环左移一个.那么第二次还是对1 到 k个元素做和第一次一 ...

  6. 【AtCoder】AGC014

    AGC014 链接 A - Cookie Exchanges 发现两个数之间的差会逐渐缩小,所以只要不是三个数都相同,那么log次左右一定会得到答案 #include <bits/stdc++. ...

  7. Atcoder Grand-014 Writeup

    A - Cookie Exchanges 题面 Takahashi, Aoki and Snuke love cookies. They have A, B and C cookies, respec ...

  8. AtCoder Grand Contest 014

    AtCoder Grand Contest 014 A - Cookie Exchanges 有三个人,分别有\(A,B,C\)块饼干,每次每个人都会把自己的饼干分成相等的两份然后给其他两个人.当其中 ...

  9. A@GC*014

    A@GC*014 A Cookie Exchanges 卡时跑了1s就输出-1 每次操作会使三个数的极差缩小一半,所以最多\(\log\)次之后就会出现\(A=B=C\)的情况,可以直接判掉 B Un ...

随机推荐

  1. Android教程2020 - RecyclerView实际使用

    示例,用RecyclerView的item做出一个列表. Android教程2020 - 系列总览 本文链接 前面我们已经知道如何用RecyclerView显示一列数据.这里我们做出一个具体的例子.尽 ...

  2. windows 安装mongodb2

    安装文件:mongodb-win32-x86_64-2008plus-ssl-3.2.6-signed.msi 电脑配置:win7 64位 MongoDB的安装很简单,设置好安装路径后,一直Next直 ...

  3. qt creator源码全方面分析(2)

    目录 doc文件夹 帮助文档 qdoc工具 doxygen工具 qtcreator.qdocconf qtcreator-dev.qdocconf doc文件夹 对于bin和dist文件夹这里就不做过 ...

  4. C++内存管理笔记(一)

      C++内存分配的四个层面 : 四个层面的比较: 内存分配与释放的测试: ); //512 bytes free(p1); complex<int>* p2 = new complex& ...

  5. 编写一个函数,输入n为偶数时,调用方法求1/2+1/4+...+1/n,当输入n为奇数时,调用函数1/1+1/3+...+1/n

    需求:编写一个函数,输入n为偶数时,调用方法求1/2+1/4+...+1/n,当输入n为奇数时,调用函数1/1+1/3+...+1/n package com.Summer_0511.cn; impo ...

  6. copy constructor和copy assignment operator的区别

    拷贝构造函数(copy constructor)被用来以一个对象来初始化同类型的另一个对象,拷贝赋值运算符(copy assignment operator)被用来将一个对象中的值拷贝到同类型的另一个 ...

  7. Codeforces_739_B

    http://codeforces.com/problemset/problem/739/B dfs,记录距离前缀和,每次找到离最近的不符合的点. #include<iostream> # ...

  8. 题解 CF1292A 【NEKO's Maze Game】

    有一个结论: 当 \((1,1)\) 不能抵达 \((2,n)\) 时,必定存在一个点对,这两个点的值均为真,且坐标中的 \(x\) 互异,\(y\) 的差 \(\leq 1\) 这个结论的正确性感觉 ...

  9. Redis Cluster 集群扩容与收缩

    http://blog.csdn.net/men_wen/article/details/72896682 Redis 学习笔记(十五)Redis Cluster 集群扩容与收缩 标签: redis集 ...

  10. ubuntu16.04 自建源

    来自于https://www.cnblogs.com/liangqihui/p/7150066.html APT本地源的搭建(可用于局域网apt-get源搭建或者本地源) 本文档介绍使用apt-mir ...