Sequence
Time Limit: 5000MS   Memory Limit: 65536K
Total Submissions: 6893   Accepted: 1534
Case Time Limit: 2000MS

Description

Given a sequence, {A1, A2, ..., An} which is guaranteed A1 > A2, ..., An,  you are to cut it into three sub-sequences and reverse them separately to form a new one which is the smallest possible sequence in alphabet order.

The alphabet order is defined as follows: for two sequence {A1, A2, ..., An} and {B1, B2, ..., Bn}, we say {A1, A2, ..., An} is smaller than {B1, B2, ..., Bn} if and only if there exists such i ( 1 ≤ in) so that we have Ai < Bi and Aj = Bj for each j < i.

Input

The first line contains n. (n ≤ 200000)

The following n lines contain the sequence.

Output

output n lines which is the smallest possible sequence obtained.

Sample Input

5
10
1
2
3
4

Sample Output

1
10
2
4
3

Hint

{10, 1, 2, 3, 4} -> {10, 1 | 2 | 3, 4} -> {1, 10, 2, 4, 3}
白书上的题目。第一道后缀数组,直接看了答案,但是没看懂。。。
第一段翻转很好求,直接翻转然后后缀数组。第二段第三段则有些问题,因为可能第二段比较短,虽然最小,但是是其他某个串的前缀,可能会出错(自己yy的,网上有反例)

9
8 4 -1 5 0 5 0 2 3
第一步:
3 2 0 5 0 5 -1 4 8 对应输出 -1 4 8
第二步
3 2 0 5 0 5(开始的时候我并没有复制一遍) 对应输出:0 5
第三步
3 2 0 5    对应输出: 3 2 0 5
可以看见这样做是不对的。。
必须要将剩下的字符串复制一遍贴在后面,然后再来求后缀数组。。。
正解:
第一步:
3 2 0 5 0 5 -1 4 8 对应输出 -1 4 8
第二步
3 2 0 5 0 5 3 2 0 5 0 5 对应输出: 0 5 0 5;
第三步
3 2 对应输出:3 2;

最后值得注意的是此题还要用离散化。。因为并没有告诉我们输入的数据有多大。。。。。(其实不用离散化,离散化是因为用的基数排序,快排就没这个问题了)


然后就是把第一段截掉剩余的东西翻转,复制一遍接在后面,再做后缀数组。

程序里的第二个循环值得注意,当p2=m-sa[i]+1+p1 p1<p2<n时成立退出,为什么是这个式子?这里我也不太懂,但是我们可以发现,当sa[i]位于复制后的字符串的前一段是才可以,那么sa[i]肯定是小于m的,

8 7 6 5 4 3 8 7 6 5 4 3 sa[i]=3

注意,是sa[i]=3,所以我们截得的字符串不是8 7 6和5 4 3 而是8 7和6 5 4 3,因为sa[i]表示的是这个位置到结尾的后缀。所以我们的第二串长度是m-sa[i]+1,在原串中的位置是p1+len=p1+m-sa[i]+1

那么我们可以发现p1<p2<n。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 400010
int n,m,k;
int a[N],rank[N],temp[N],sa[N],rev[N];
bool cp(int i,int j)
{
if(rank[i]!=rank[j]) return rank[i]<rank[j];
int ri=i+k<=n?rank[i+k]:-;
int rj=j+k<=n?rank[j+k]:-;
return ri<rj;
}
void Sa(int a[],int n)
{
for(int i=;i<=n;i++)
{
sa[i]=i; rank[i]=a[i];
}
for(k=;k<=n;k*=)
{
sort(sa+,sa+n+,cp);
temp[sa[]]=;
for(int i=;i<=n;i++)
temp[sa[i]]=temp[sa[i-]]+(cp(sa[i-],sa[i]));
for(int i=;i<=n;i++) rank[i]=temp[i];
}
}
void solve()
{
reverse_copy(a+,a+n+,rev+);
Sa(rev,n);
int p1=;
for(int i=;i<=n;i++)
{
p1=n-sa[i]+;
if(p1>&&n-p1>=) break;
}
memset(rev,,sizeof(rev));
int m=n-p1;
reverse_copy(a+p1+,a+n+,rev+);
reverse_copy(a+p1+,a+n+,rev+m+);
Sa(rev,*m);
int p2=;
for(int i=;i<=*m;i++)
{
p2=m-sa[i]++p1;
if(p2>p1&&p2<n) break;
}
for(int i=p1;i>=;i--) printf("%d\n",a[i]);
for(int i=p2;i>p1;i--) printf("%d\n",a[i]);
for(int i=n;i>p2;i--) printf("%d\n",a[i]);
}
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++)
{
scanf("%d",&a[i]);
}
solve();
return ;
}

poj3581的更多相关文章

  1. [POJ3581]Sequence

    [POJ3581]Sequence 题目大意: 给定序列\(A_{1\sim n}\),其中\(A_1\)为最大的数.要把这个序列分成\(3\)个非空段,并将每一段分别反转,求能得到的字典序最小的序列 ...

  2. POJ3581 Sequence —— 后缀数组

    题目链接:https://vjudge.net/problem/POJ-3581 Sequence Time Limit: 5000MS   Memory Limit: 65536K Total Su ...

  3. POJ3581 Sequence(后缀数组)

    题意:给一个串,串的第一个字符比后面的都大,要把它分成三段,然后反转每一段,求能得到的字典序最小的串是什么. 首先,第一段是可以确定的:把原串反转,因为第一个字符是最大的,它是唯一的,不存在反转串的后 ...

  4. POJ3581:Sequence(后缀数组)

    Description Given a sequence, {A1, A2, ..., An} which is guaranteed A1 > A2, ..., An,  you are to ...

  5. POJ3581 后缀数组

    http://poj.org/problem?id=3581 这题说是给了N个数字组成的序列A1 A2 ..An 其中A1 大于其他的数字 , 现在要把序列分成三段并将每段分别反转求最小字典序 以后还 ...

  6. POJ3581:Sequence——题解

    http://poj.org/problem?id=3581 给一串数,将其分成三个区间并且颠倒这三个区间,使得新数列字典序最小. 参考:http://blog.csdn.net/libin56842 ...

  7. 【后缀数组】poj3581 Sequence

    考虑第一次切割,必然切割的是翻转后字典序最小的前缀,伪证: 若切割位置更靠前:则会导致第一个数翻转后更靠前,字典序必然更大. 若切割位置更靠后,则显然也会导致字典序更大. ↑,sa即可 对于第二次切割 ...

  8. sa learning

    后缀数组之前一直在给队友搞,但是这个类太大了,预感到青岛八成会有,于是自己也学习一下,记录一下做题的历程 所用的模板暂时来自于队友的倍增nlogn da算法 int t1[maxn] , t2[max ...

随机推荐

  1. CentOS 7 下安装redis步骤

    1. 从redis官网下载redis源码,本例安装在/usr/opt下 [root@localhost opt]# pwd /usr/opt [root@localhost opt]# wget ht ...

  2. 细谈Slick(5)- 学习体会和将来实际应用的一些想法

    通过一段时间的学习和了解以及前面几篇关于Slick的讨论后对Slick这个函数式数据库编程工具有了些具体的了解.回顾我学习Slick的目的,产生了许多想法,觉着应该从实际的工作应用角度把我对Slick ...

  3. bootstrap(关于栅格布局)

    栅格系统是通过行(.row)与列(column)的组合一起来创建页面布局的,所以只有列(column)可以作为行(row)的直接子元素,我们所要写的内容可以放在列里(column),不过在行的外层还需 ...

  4. 深入理解DOM节点类型第二篇——文本节点Text

    × 目录 [1]特征 [2]空白 [3]属性[4]方法[5]性能 前面的话 文本节点顾名思义指向文本的节点,网页上看到的文字内容都属于文本节点.该节点简单直观,本文将详细介绍该部分内容 特征 文本节点 ...

  5. BW知识问答汇总

    什么是sap的星型结构,能不能详细讲解一下? Cube的星型结构中SID技术的优点有哪些? 什么是BW的星型结构,与传统的星型结构的区别是什么? SAP的星型结构相对于传统的星型结构优势? Cube与 ...

  6. 服务器开启https协议

    开启Tomcat https服务 发布企业级应用的时候遇到一个问题,就是IOS7.1之后app的下载地址URL必须是https开头的协议,所以服务器必须支持https协议. 实验环境:Mac OSX ...

  7. [tableView reloadData] 和 runloop

    需要[tableView reloadData]后需要立即获取tableview的cell.高度,或者需要滚动tableview,那么,直接在reloadData后执行代码是会有问题的. 断点调试感觉 ...

  8. C#语言基础——函数

    函数一个较大的程序一般应分为若干个程序块,每一个模块用来实现一个特定的功能.所有的高级语言中都有子程序这个概念,用子程序实现模块的功能.在C#语言中,子程序的作用是由一个主函数和若干个函数构成.由主函 ...

  9. MySQL函数

    MySQL数据库提供了很多函数包括: 数学函数: 字符串函数: 日期和时间函数: 条件判断函数: 系统信息函数: 加密函数: 格式化函数: 一.数学函数 数学函数主要用于处理数字,包括整型.浮点数等. ...

  10. 如何在mac上用终端打开XAMPP自带的MySQL

    注:1.本文未经博主同意,不得转载! 2.所有终端语句都分行显示,以免大家看错: 直接开始,过程中对每一步可能出现的错误都进行了说明. 1.安装好xampp,然后打开终端,输入: mysql -u r ...