[POJ3581]Sequence
[POJ3581]Sequence
题目大意:
给定序列\(A_{1\sim n}\),其中\(A_1\)为最大的数。要把这个序列分成\(3\)个非空段,并将每一段分别反转,求能得到的字典序最小的序列。
思路:
对于第一段,由于\(A_1\)是最大的数字,因此我们可以将\(A_{1\sim n}\)翻转,用后缀数组求最小后缀作为第一段。
对于剩下两段,如果仍然套用第一段的方法是行不通的。下面是反例:
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,此时最终答案就变成了-1 4 8 0 5 3 2 0 5,而我们不难发现最优解其实是-1 4 8 0 5 0 5 3 2。
那么,问题出在哪里呢?
事实上,题目让我们求的是操作后整个序列字典序最小,因此我们在计算第二段是也需要考虑第三段的影响。我们不妨将去掉第一段后剩下的序列复制两遍接起来,求起点在前面一半的最小后缀。还是以上文的数据为例,将3 2 0 5 0 5改成3 2 0 5 0 5 3 2 0 5 0 5。此时我们求得最小后缀为0 5 0 5 3 2 0 5 0 5。第二段为0 5 0 5,第三段为3 2。因此得到最后序列为-1 4 8 0 5 0 5 3 2。
使用倍增+快排的后缀数组,时间复杂度是\(\mathcal O(n\log^2 n)\)的。
源代码:
#include<cstdio>
#include<cctype>
#include<algorithm>
inline int getint() {
register char ch;
register bool neg=false;
while(!isdigit(ch=getchar())) neg|=ch=='-';
register int x=ch^'0';
while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
return neg?-x:x;
}
const int N=2e5;
int n,k,a[N],sa[N*2],rank[N*2],tmp[N*2],rev[N*2];
inline bool cmp(const int &i,const int &j) {
if(rank[i]!=rank[j]) return rank[i]<rank[j];
const int ri=i+k<n?rank[i+k]:-1;
const int rj=j+k<n?rank[j+k]:-1;
return ri<rj;
}
inline void suffix_sort(const int &nn) {
n=nn;
for(register int i=0;i<n;i++) {
sa[i]=i;
rank[i]=i<n?rev[i]:-1;
}
for(k=1;k<=n;k<<=1) {
std::sort(&sa[0],&sa[n],cmp);
tmp[sa[0]]=0;
for(register int i=1;i<n;i++) {
tmp[sa[i]]=tmp[sa[i-1]]+!!cmp(sa[i-1],sa[i]);
}
for(register int i=0;i<n;i++) {
rank[i]=tmp[i];
}
}
}
int main() {
const int n=getint();
for(register int i=0;i<n;i++) a[i]=getint();
std::reverse_copy(&a[0],&a[n],&rev[0]);
suffix_sort(n);
int p1=0,p2=0;
for(register int i=0;i<n&&(p1<1||n-p1<2);i++) {
p1=n-sa[i];
}
const int m=n-p1;
std::reverse_copy(&a[p1],&a[n],&rev[0]);
std::reverse_copy(&a[p1],&a[n],&rev[m]);
suffix_sort(m*2);
for(register int i=0;i<m*2&&(p2-p1<1||n-p2<1);i++) {
p2=n-sa[i];
}
std::reverse(&a[0],&a[p1]);
std::reverse(&a[p1],&a[p2]);
std::reverse(&a[p2],&a[n]);
for(register int i=0;i<n;i++) {
printf("%d\n",a[i]);
}
return 0;
}
[POJ3581]Sequence的更多相关文章
- POJ3581 Sequence —— 后缀数组
题目链接:https://vjudge.net/problem/POJ-3581 Sequence Time Limit: 5000MS Memory Limit: 65536K Total Su ...
- POJ3581:Sequence(后缀数组)
Description Given a sequence, {A1, A2, ..., An} which is guaranteed A1 > A2, ..., An, you are to ...
- POJ3581 Sequence(后缀数组)
题意:给一个串,串的第一个字符比后面的都大,要把它分成三段,然后反转每一段,求能得到的字典序最小的串是什么. 首先,第一段是可以确定的:把原串反转,因为第一个字符是最大的,它是唯一的,不存在反转串的后 ...
- 【后缀数组】poj3581 Sequence
考虑第一次切割,必然切割的是翻转后字典序最小的前缀,伪证: 若切割位置更靠前:则会导致第一个数翻转后更靠前,字典序必然更大. 若切割位置更靠后,则显然也会导致字典序更大. ↑,sa即可 对于第二次切割 ...
- POJ3581:Sequence——题解
http://poj.org/problem?id=3581 给一串数,将其分成三个区间并且颠倒这三个区间,使得新数列字典序最小. 参考:http://blog.csdn.net/libin56842 ...
- oracle SEQUENCE 创建, 修改,删除
oracle创建序列化: CREATE SEQUENCE seq_itv_collection INCREMENT BY 1 -- 每次加几个 STA ...
- Oracle数据库自动备份SQL文本:Procedure存储过程,View视图,Function函数,Trigger触发器,Sequence序列号等
功能:备份存储过程,视图,函数触发器,Sequence序列号等准备工作:--1.创建文件夹 :'E:/OracleBackUp/ProcBack';--文本存放的路径--2.执行:create or ...
- DG gap sequence修复一例
环境:Oracle 11.2.0.4 DG 故障现象: 客户在备库告警日志中发现GAP sequence提示信息: Mon Nov 21 09:53:29 2016 Media Recovery Wa ...
- Permutation Sequence
The set [1,2,3,-,n] contains a total of n! unique permutations. By listing and labeling all of the p ...
随机推荐
- Android应用程序App应用上线流程
对于很多初级开发者,可能对app应用上线不太了解,本文跟大家介绍一下怎么上线app应用.上线App并不是一件很困难的事情,App的应用功能也不需要很强大,甚至不用联网,只有简单的一两个页面的App应用 ...
- Eclipse svn 忽略文件夹/ svn 设置不同步
Eclipse 开发中我们经常用到SVN插件, 但是对于某些文件的缓存来说, 我们只要有操作缓存便会保存一次, 每次提交很是麻烦, 小编这里教你一种不同步某个文件夹的方法 工具/原料 MyEclips ...
- Java回收方法区中回收的类
回收的类必须满足下面三个条件才能算是“无用的类” 1.该类所有的实例都已经被回收,也就是说Java堆中不存在该类的任何实例: 2.加载该类的ClassLoader已经被回收: 3.该类对应的java. ...
- MongoDB的安装配置、基本操作及Perl操作MongoDB
MongoDB的安装配置.基本操作及Perl操作MongoDB http://www.myhack58.com/Article/60/63/2014/42353.htm
- python3使用xlrd、xlwt、xlutils、openpyxl、xlsxwriter操作excel
特色简介 xlrd主要用来读excel,针对.xls格式: xlwt主要用来写excel,针对.xls格式,超出excel 的单格内容长度上限32767,就会报错: xlutils结合xlrd可以达到 ...
- FIS3 大白话【一】
1.fis3可以用fis.set进行一些全局的配置,包括忽略文件.文件后缀处理类型.源码过滤等等,用fis3.get可以得到配置信息,详见: http://fis.baidu.com/fis3/doc ...
- socket.io入门整理
我自己在用socket.io开发,对官方网站上的文档,进行简单的整理,然后自己写了一个简单的聊天程序. 最最开始 先安装socket.io: 1 npm install socket.io 利用Nod ...
- [How to] UIScrollView的使用方法
1.简介 代码 延续前一个博客使用Xib来创建view,本文我们创建一个带有PageControlView的ScrollView的table的headView,如下图: 具有自动滚动: 具有拖拽完毕后 ...
- Microsoft .NET Native
首页: https://msdn.microsoft.com/en-US/vstudio/dotnetnative
- node采用的commonJs规范
AMD与commonJS规范不同 同步加载 主要就是一个输出,一个引入,我也建了两个文件,一个输出文件一个引入文件 export.js ; ; ; function incCounter(){ cou ...