题目链接:https://vjudge.net/problem/POJ-3581

Sequence
Time Limit: 5000MS   Memory Limit: 65536K
Total Submissions: 7754   Accepted: 1761
Case Time Limit: 2000MS

Description

Given a sequence, {A1A2, ..., An} which is guaranteed AA2, ..., 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 {A1A2, ..., An} and {B1B2, ..., Bn}, we say {A1A2, ..., An} is smaller than {B1B2, ..., Bn} if and only if there exists such i ( 1 ≤ i ≤ n) 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}

Source

题意:

给出一个字符串,将其分成三段,并且将每一段翻转。求翻转过后字典序最小的一个。

题解:

1.分成三段,即求出两个分割点,于是分两部分进行求解。

2.第一部分:求第一段。由于求的是翻转过后字典序最小的,那么先将原字符串翻转得到逆串,然后求其后缀数组。那么排名最靠前且满足能分成三段的那个后缀,即为翻转过后的第一段。 形如:1 1 2 2 3 3 等最小值重复出现在前面的串,如果直接求其逆串的后缀数组,那么排名最靠前的是“1”,而我们的目标是“1 1”,但题目说明了 A1>A2……An,因此不会出现这种情况。

3.第二部分:将剩余的逆串复制多一分接在后面,然后求其后缀数组,接下来的做法与第一步类似。

4. 为什么第二部分需要复制多一份在末尾,而第一部分不用呢?

答:由于题目声明了A1>A2……An,所以直接求其后缀数组,并得到排名最靠前且满足能分成三段的那个后缀,因为不会出现形如“1 1 2 2 3 3”的串,所以这个后缀一定是最优的;然而,去掉第一段之后,剩下的逆串的原串就可能为类似“1 1 2 2 3 3”的串,即逆串为“3 3 2 2 1 1”,如果直接求其后缀数组,那么得到的第二段为“1”,而我们的目标是“1 1”。为了解决这个问题,可以复制多一份接在后面得到“3 3 2 2 1 1 3 3 2 2 1 1”,然后求后缀数组,取位置在0~len-1且排名靠前且满足能分成两段的。

代码如下:

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
using namespace std;
typedef long long LL;
const int INF = 2e9;
const LL LNF = 9e18;
const int MOD = 1e9+;
const int MAXN = 4e5+; bool cmp(int *r, int a, int b, int l)
{
return r[a]==r[b] && r[a+l]==r[b+l];
} int r[MAXN], sa[MAXN], Rank[MAXN], height[MAXN];
int t1[MAXN], t2[MAXN], c[MAXN];
void DA(int str[], int sa[], int Rank[], int height[], int n, int m)
{
n++;
int i, j, p, *x = t1, *y = t2;
for(i = ; i<m; i++) c[i] = ;
for(i = ; i<n; i++) c[x[i] = str[i]]++;
for(i = ; i<m; i++) c[i] += c[i-];
for(i = n-; i>=; i--) sa[--c[x[i]]] = i;
for(j = ; j<=n; j <<= )
{
p = ;
for(i = n-j; i<n; i++) y[p++] = i;
for(i = ; i<n; i++) if(sa[i]>=j) y[p++] = sa[i]-j; for(i = ; i<m; i++) c[i] = ;
for(i = ; i<n; i++) c[x[y[i]]]++;
for(i = ; i<m; i++) c[i] += c[i-];
for(i = n-; i>=; i--) sa[--c[x[y[i]]]] = y[i]; swap(x, y);
p = ; x[sa[]] = ;
for(i = ; i<n; i++)
x[sa[i]] = cmp(y, sa[i-], sa[i], j)?p-:p++; if(p>=n) break;
m = p;
} int k = ;
n--;
for(i = ; i<=n; i++) Rank[sa[i]] = i;
for(i = ; i<n; i++)
{
if(k) k--;
j = sa[Rank[i]-];
while(str[i+k]==str[j+k]) k++;
height[Rank[i]] = k;
}
} int a[MAXN], M[MAXN];
int main()
{
int n;
scanf("%d", &n);
for(int i = ; i<n; i++)
scanf("%d", &a[i]);
memcpy(M, a, sizeof(M));
sort(M, M+n);
int m = unique(M, M+n)-M;
for(int i = ; i<n; i++) //离散化
r[i] = upper_bound(M, M+m, a[i])-M;
reverse(r, r+n); int pos1, pos2;
r[n] = m+; //在翻转过后的串尾加个最大值,以保证 “1 1 2 2 3 3” 的情况下第一段取的是“2 2”, 而不是“2”
r[n+] = ; //再加上串尾结束符
DA(r, sa, Rank, height, n+, m+);
for(int i = ; i<=n; i++)
if(n--sa[i]<=n-) //第一段至多只能到n-3的地方,不然就不能分成三段了
{
pos1 = n--sa[i];
break;
} int len = n-pos1-;
for(int i = ; i<len; i++) //将剩下的串复制多一份接在后面,中间无需分隔符。
r[len+i] = r[i];
len *= ;
r[len] = ;
DA(r, sa, Rank, height, len, m+);
for(int i = ; i<=len; i++)
if(sa[i]<len/ && n-sa[i]-<=n-) //第二段至多只能到n-2的地方,不然就将剩下的分成两段了
{
pos2 = n-sa[i]-;
break;
} // printf("%d %d\n", pos1, pos2);
for(int i = pos1; i>=; i--) printf("%d\n", a[i]);
for(int i = pos2; i>pos1; i--) printf("%d\n", a[i]);
for(int i = n-; i>pos2; i--) printf("%d\n", a[i]);
}

最新文章

  1. 此操作失败的原因是对 IID 为“{000208DA-0000-0000-C000-000000000046}”的接口的 COM 组件调用 QueryInterface
  2. 用html5+js实现掌机游戏赛车demo
  3. 9.Android之日期对话框DatePicker控件学习
  4. IIS负载均衡-Application Request Route详解第一篇: ARR介绍(转载)
  5. div+css样式表的id,class的常用命名规则
  6. Jquery 简单的Tab选项卡特效
  7. Android TabActivity之感叹
  8. html5 web worker
  9. [Aaronyang] 写给自己的WPF4.5 笔记15[AyArc诞生-WPF版本绚丽的环状图,Ay制作,AyWindow强势预览]
  10. 一张表搞清楚php is_null、empty、isset的区别
  11. 分享一个不错的Unittest测试报告
  12. es6 语法 (对象扩展)
  13. ZOJ 1456 Minimum Transport Cost(Floyd算法求解最短路径并输出最小字典序路径)
  14. Error creating bean with name &#39;enableRedisKeyspaceNotificationsInitializer&#39; defined in class path resource
  15. [转帖]nginx upstream模块--负载均衡
  16. LeetCode(4):两个排序数组的中位数
  17. 解决SQLite异常:library routine called out of sequence
  18. tp5安装验证码
  19. 转:在centos安装与启动mysql
  20. POJ3666序列最小差值

热门文章

  1. Oracle内存管理(之五)
  2. RAM和ROM和Flash ROM的区别
  3. Command &amp;Prompt Here
  4. 如何在DOS窗口中显示UTF-8字符
  5. 前端PC页面,移动端页面问题笔记~~
  6. mysql中把空值放在最后,有值的数据放在前面
  7. Linux内核源码分析方法_转
  8. fzu 2039 Pets (简单二分图 + (最大流 || 二分图))
  9. jQuery中slideToggle()的详细使用方法和解释
  10. 关于spring的bean