POJ 3581 Sequence(后缀数组)
2024-08-26 02:01:01
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 ≤ 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}
题意:将数组划分成三分,分别翻转,求翻转后字典序最小的
题解:首先将原数组首尾倒转,后缀数组找出字典序最小的后缀,然后再把剩下的翻转,再用后缀数组找出最小的后缀,然后就稳了
代码如下:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std; int n,k,pos,a[],b[],c[],sa[],rk[],tmp[]; int cmp(int i,int j)
{
if(rk[i]!=rk[j]) return rk[i]<rk[j];
int ri=i+k<=n?rk[i+k]:-;
int rj=j+k<=n?rk[j+k]:-;
return ri<rj;
} int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++)
{
scanf("%d",&a[i]);
b[n-i]=a[i];
}
for(int i=;i<n;i++)
{
sa[i]=i;
rk[i]=b[i];
}
sa[n]=n;
rk[n]=-;
for(k=;k<=n;k<<=)
{
sort(sa,sa+n+,cmp);
tmp[sa[]]=;
for(int i=;i<=n;i++)
{
tmp[sa[i]]=tmp[sa[i-]]+cmp(sa[i-],sa[i]);
}
for(int i=;i<=n;i++)
{
rk[i]=tmp[i];
}
}
sort(sa,sa+n+,cmp);
for(int i=;i<=n;i++)
{
if(sa[i]!=&&sa[i]!=&&sa[i]!=n)
{
pos=sa[i];
break;
}
}
int len=n-pos;
int cnt=;
for(int i=n;i>=len+;i--)
{
c[cnt++]=a[i];
}
for(int i=cnt;i<cnt*;i++)
{
c[i]=c[i-cnt];
}
n=cnt*;
for(int i=;i<n;i++)
{
sa[i]=i;
rk[i]=c[i];
}
sa[n]=n;
rk[n]=-;
for(k=;k<=n;k<<=)
{
sort(sa,sa+n+,cmp);
tmp[sa[]]=;
for(int i=;i<=n;i++)
{
tmp[sa[i]]=tmp[sa[i-]]+cmp(sa[i-],sa[i]);
}
for(int i=;i<=n;i++)
{
rk[i]=tmp[i];
}
}
for(int i=len;i>=;i--)
{
printf("%d\n",a[i]);
}
sort(sa,sa+n+,cmp);
for(int i=;i<=n;i++)
{
if(sa[i]+n/<n&&sa[i]!=)
{
for(int j=sa[i];j<=sa[i]+n/-;j++)
{
printf("%d\n",c[j]);
}
break;
}
}
}
最新文章
- Docker安装CentOS
- Maven安装配置使用
- Mac 制作 10.11.3 U盘安装盘
- [Unity3D] 浅尝Unity3D
- cf112a(水题)
- codevs 1506 传话
- nandflash学习1——导致nandflash反转的原因【转】
- MFC下拉框使用方法
- zoj 3672 思考题
- sqlserver 时间 格式化
- UVa 340 Master-Mind Hints (优化查找&;复制数组)
- clearcase常用命令
- 快速排序算法之我见(附上C代码)
- 图片上传插件用法,JS语法【三】
- 如何通过Visual Studio来管理我们的数据库项目
- poj 2459 Sumsets
- Supervisor使用说明
- C#单问号(?)与双问号(??)
- .30-浅析webpack源码之doResolve事件流(2)
- 批量生成protoBuf到cs文件