[POJ 3581]Sequence
[POJ 3581]Sequence
标签: 后缀数组
题意
给你一串序列\(A_i\),保证对于$ \forall i \in [2,n],都有A_1 >A_i$。
现在需要把这个序列分成三段,并且将这三段分别翻转,求如何翻转使整个序列字典序最小。(每一段不能为空)
题解
首先可以确定第一段的位置。
注意到,\(A_1\)是最大的,所以我们就只用考虑怎样找到一个前缀使其翻转后的字典序最小。
(假如不是的话,就可能找到两个前缀翻转之后,一个为另一个的前缀,无法解决)
这等价于翻转之后找到一个后缀使其字典序最小,用后缀数组处理一下。
然后确定第二段的位置。
先翻转之后,找一个分割点使整个串最小。这等价于最小循环表示法问题。
可以直接用后缀数组解决,也有O(n)的做法。
Code
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std;
#define ll long long
#define REP(i,a,b) for(int i=(a),_end_=(b);i<=_end_;i++)
#define DREP(i,a,b) for(int i=(a),_end_=(b);i>=_end_;i--)
#define EREP(i,a) for(int i=start[(a)];i;i=e[i].next)
inline int read()
{
int sum=0,p=1;char ch=getchar();
while(!(('0'<=ch && ch<='9') || ch=='-'))ch=getchar();
if(ch=='-')p=-1,ch=getchar();
while('0'<=ch && ch<='9')sum=sum*10+ch-48,ch=getchar();
return sum*p;
}
const int maxn=4e5+20;
int n,a[maxn],sa[maxn],S[maxn],cnt;
void init()
{
n=read();
REP(i,0,n-1)a[i]=read(),S[cnt++]=a[i];
sort(S,S+cnt);
cnt=unique(S,S+cnt)-S;
REP(i,0,n-1)a[i]=lower_bound(S,S+cnt,a[i])-S;
}
int r[maxn*2];
int x[maxn],y[maxn]={0},bug[maxn]={0},v[maxn*2];
void suffix_array(int *r,int n)
{
int p=0,m=200000;
memset(v,-1,sizeof(v));
REP(i,0,m)bug[i]=0;
REP(i,0,n-1)bug[x[i]=r[i]]++;
REP(i,1,m)bug[i]+=bug[i-1];
DREP(i,n-1,0)sa[--bug[x[i]]]=i;
for(int j=1;p<n;j*=2,m=p)
{
p=0;REP(i,n-j,n-1)y[p++]=i;
REP(i,0,n-1)if(sa[i]>=j)y[p++]=sa[i]-j;
REP(i,0,m)bug[i]=0;
REP(i,0,n-1)bug[v[i]=x[y[i]]]++;
REP(i,1,m)bug[i]+=bug[i-1];
DREP(i,n-1,0)sa[--bug[v[i]]]=y[i];
REP(i,0,n-1)v[i]=x[i];p=1;x[sa[0]]=0;
REP(i,1,n-1)x[sa[i]]=v[sa[i-1]]==v[sa[i]] && v[sa[i-1]+j]==v[sa[i]+j] ?p-1:p++;
}
}
void doing()
{
REP(i,0,n-1)r[i]=a[n-i-1];
suffix_array(r,n);
int X=0;
REP(i,0,n-1)if(sa[i]>1){X=sa[i];break;}
REP(i,X,n-1)cout<<S[r[i]]<<endl;
//REP(i,0,n-X-1)x[i]=a[i+X+1];
n=X;
REP(i,n,2*n-1)r[i]=r[i-n];
suffix_array(r,2*n);
REP(i,0,2*n-1)if(sa[i]<n && sa[i]){X=sa[i];break;}
REP(i,X,n-1+X)cout<<S[r[i]]<<endl;
}
int main()
{
init();
doing();
return 0;
}
[POJ 3581]Sequence的更多相关文章
- POJ 3581 Sequence(后缀数组)
[题目链接] http://poj.org/problem?id=3581 [题目大意] 给出一个数列,将这个数列分成三段,每段分别翻转,使得其字典序最小,输出翻转后的数列. [题解] 首先,第一个翻 ...
- POJ 3581 Sequence [后缀数组]
Sequence Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 6911 Accepted: 1543 Case Tim ...
- POJ 3581 Sequence(后缀数组)
Description Given a sequence, {A1, A2, ..., An} which is guaranteed A1 > A2, ..., An, you are to ...
- 后缀数组 POJ 3581 Sequence
题目链接 题意:把n个数字(A1比其他数字都大)的序列分成三段,每段分别反转,问字典序最小的序列. 分析:因为A1比其他数字都大,所以反转后第一段结尾是很大的数,相当是天然的分割线,第一段可以单独考虑 ...
- POJ 3581 Sequence ——后缀数组 最小表示法
[题目分析] 一见到题目,就有了一个显而易见obviously的想法.只需要每次找到倒过来最小的那一个字符串翻转就可以了. 然而事情并不是这样的,比如说505023这样一个字符串,如果翻转了成为320 ...
- POJ 3581 Sequence(后缀数组)题解
题意: 已知某字符串\(str\)满足\(str_1 > max\{str_2,str_3 \cdots str_n\}\),现要求把这个字符串分成连续的三组,然后每组都翻转,问字典序最小是什么 ...
- POJ 3581:Sequence(后缀数组)
题目链接 题意 给出n个数字的序列,现在让你分成三段,使得每一段翻转之后拼接起来的序列字典序最小.保证第一个数是序列中最大的数. 例如样例是{10, 1, 2, 3, 4},分成{1, 10}, {2 ...
- Sequence POJ - 3581 后缀数组
题意: 将一个序列分成非空的三部分,将每部分翻转后组合成一个新的序列, 输出这样操作得到的序列中字典序最小的序列 (保证第一个数是数组中最大的元素) 题解: 把数组当作串串. 因为第一个数最大,所以我 ...
- POJ 2442 Sequence
Pro. 1 给定k个有序表,取其中前n小的数字.组成一个新表,求该表? 算法: 由于 a1[1] < a1[2] < a1[3] ... <a1[n] a2[1] < a2 ...
随机推荐
- 基于FPGA的HDMI高清显示接口驱动
HDMI是(High Definition Multimedia Interface)的缩写,意思是高清晰度多媒体接口,是一种数字化视频/音频接口技术,适合影像传输的专用型数字化接口,可同时传送音频和 ...
- -pie can only be used when targeting iOS 4.2 or later错误解决
在工程的build setting里,把IPHONEOS_DEPLOYMENT_TARGET改成4.2或以上就行了
- DALI调色温
DALI调色温模块使用手册 公 司: 深圳市万秀电子有限公司 网 站: http://www.wanxiucx.com 总 机: 0755-23215689 联系人: 张先生 手 机: 139 ...
- Oracle问题之ORA-01031权限不足
Oracle问题之ORA-01031权限不足 此时应该按照如下写: sqlplus /nolog conn / as sysdba shutdown immediate 本地以sysdba身份登录数据 ...
- Android 双卡获取当前使用流量在线卡的信息
最近接触了一个项目,需要获取在线流量卡的信息,下面的方式,可以获取大部分手机的正确手机卡信息. 一 获取获取IMEI public static String getDeviced(int solt ...
- linux_常用命令_2
rev 反向读取, reverse echo 123456 | rev # 结果为 654321 rev Name.txt # 行号没变,每一行的数据翻转过来 less 具有more命令所有功能,更加 ...
- JavaScript数组的22种方法
原文:http://www.cnblogs.com/xiaohuochai/p/5682621.html javascript中数组的22种方法 前面的话 数组总共有22种方法,本文将其分为对象继 ...
- pulltorefresh 设置刷新文字提示颜色
xmlns:ptr="http://schemas.android.com/apk/res-auto" 赵泽民 2016/7/12 15:48:58 ptr:ptrHeaderS ...
- WebView加载html5页面
mWebView = (WebView) findViewById(R.id.mwebview); mWebView.getSettings().setJavaScriptEnabled(true); ...
- RecyclerView用法
主界面布局: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns ...