UVA 10534 - Wavio Sequence
这道题的意思是让我们求一个上升子序列 + 一个下降字序列,且两边的长度是相等的,由于用正常的 O(n2) 算法会 TLE ,所以这里我们采用二分法求最长上升子序列,这里需要利用两个栈来储存“相当于”最长上升子序列的串(我利用一个栈通过再次初始化栈顶top来第二次使用),在此同时开两个数组f1[i],f2[i],分别表示前i个元素的最长字串长度,最后比较同一个位置时(注意f1,f2一个正一个反)两个数组值的大小,取小的一个(因为要求两边长度相等)赋值给新开的数组flag[](我用num不断刷新),最后遍历数组,找出其最大的就可以了。
这里说一下二分法求最长上升子序列:复杂度为O(n×logn):
它是通过一个栈来实现的,我们遍历一个母串,如果当前值大于栈顶元素的值,我们将其压入栈,而当前位置 i 的最长上升子序列的长度就是栈顶指针的值(或+1),如果当前值等于栈顶元素的值,不压入栈,同样当前位置 i 的最长上升子序列的值就是栈顶指针的值(或+1),如果当前值小于栈顶元素的值,不压入栈,但是我们要用二分法找出恰好不小于当前值的那个位置,这个位置我们这里定义为x,并将x位置的值替换为当前值,而当前位置 i 的最长上升子序列的长度就是x这个指针的值(或+1);
为什么这样是成立的呢:别人的证明:
实际上就是运用了贪心的思想,每次进行替换操作后增强了后续最长上升子序列的“长度增长的潜力”,后续得到的解一定不会比不替换更优。
简单证明一下其正确性。我们用a[i]替换掉了S[mid],对后续某一元素a[j]来讲,可能会认为此时a[j]前的元素标号并不是严格升序了,这会不会有问题呢?实际是不会有问题的。我们不妨设a[j]左边的元素依次为A1、A2、……,这样A1我们必然可以不动,因为此前A1已经更新至最新了,标号必然是所有曾在这个位置的元素中的标号最大的一个,那么对于A2呢,我们不妨想想现在的A1刚进入这个栈的时候吧,那个时候的A2必然也在那个时候之前更新到当时的最新了吧,并且A1左边的元素的个数从那个时刻起也没有变过吧?现在这个问题就可以不断递归下去了,我们按这种方式一定可以找到一个序号严格递增的序列,即使这个序列并不是在a[j]入栈时我们所看到的序列,但这又有什么关系呢,反正结果对就是了。
再简单说明一下其最优性。既然前面已经证明了其正确性,那么按前面的方法至少可以得到一个长度可观的最长上升子序列,但究竟其是否是最长的呢?按上面算法的思路,如果想要得到的长度更长的话,那么只有一个措施,就是将原来的替换操作变成插入操作,要不然是没办法增加长度的。然而如果将替换操作变成插入操作,我们还能保证一定可以得到一个标号严格升序的上升子序列吗?显然不能。比如一次插入操作在S[k]和S[k+1]之间,我们插入了一个a[i],但是如果此时有a[j]>S[k+1],那么a[j]的左边是没办法构造出一个长度为k+2的标号严格升序的上升子序列的。既然第一次插入操作都会有错,那肯定就不用考虑后续再有插入操作了。
代码如下:
#include<stdio.h>#define MAXN 10010int a[MAXN], f[MAXN], f1[MAXN], f2[MAXN];int n,num;int up_bd(int *f, int t, int v){int m;int first = 0;while(first < t) { m = first + (t - first)/2;if(f[m] < v) first = m + 1;else t = m; } f[first] = v;return first;}void solve(){int top; top = 0; f[0] = a[0]; f1[0] = 1;int x,y;for(int i = 1; i < n; i ++) {if(a[i] > f[top]) {f[++top] = a[i];x = top + 1;}else if(a[i] == f[top]) {f[top] = a[i];x = top + 1;}else if(a[i] < f[top]) x = up_bd(f,top,a[i])+1; f1[i] = x; } top = 0; f[0] = a[n-1]; f2[0] = 1;for(int i = n-2; i >= 0; i --) {if(a[i] > f[top]) {f[++top] = a[i];y = top + 1;}else if(a[i] == f[top]) {f[top] = a[i];y = top + 1;}else if(a[i] < f[top]) y = up_bd(f,top,a[i])+1; f2[n-1-i] = y; } num = 0;int min = 0;for(int i = 0; i < n; i ++) {if(f1[i] > f2[n-i-1]) min = f2[n-i-1];else min = f1[i];if(min > num) num = min; } printf("%d\n",2*num - 1);}void input(){while(scanf("%d",&n) == 1) {for(int i = 0; i < n; i ++) scanf("%d",&a[i]); solve(); }}int main(){ input();return 0;}
转载于:https://www.cnblogs.com/yuzhaoxin/archive/2012/03/31/2427740.html
UVA 10534 - Wavio Sequence相关推荐
- uva 10534——Wavio Sequence
题意:给定一个序列,求一个最长的序列,使得他的前半部分是递增的,而后半部分是递减的,且两部分的长度一样. 思路:经典的LIS问题,和openjudge登山问题一样,前后各扫一遍,找到前置和倒置的LIS ...
- UVA 10534 Wavio Sequence DP LIS
题意:求一个波浪子序列,就是是前一半是上升子序列,后一半是下降子序列(子序列的长度必须为奇数). 分别从左右两个方向求LIS,然后在统计最大值就行了 //#pragma comment(linker, ...
- 【UVa】Wavio Sequence(dp)
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&p ...
- UVA10534 Wavio Sequence【LIS+DP】
Wavio is a sequence of integers. It has some interesting properties. • Wavio is of odd length i.e. L ...
- uva 1626 - Brackets sequence
// // main.cpp // uva 1626 - Brackets sequence/*这一题应该是经典的矩阵类似问题.显然 需要使用两个变量来表示最终的结果.设 dp[i][j]表示第i个位 ...
- UVA - 1626 Brackets sequence
题目链接 给你一个括号序列,输出一个前后括号都匹配的补全序列,且补的字符尽量少. 对一个串s来说,只会有两种情况:1.(t)或[t]转移到t 2.有两个字符,分段转移.为了保证是最小值,一定要考虑情况 ...
- UVA - 1594 Ducci Sequence
/*做这题时的心路历程其实挺有趣的一开始看到说Ducci序列最终要么全0,要么循环,我在想:要怎么判断循环呢?是不是还得记录下循环节什么的?是该用数组记录循环节吗?还是想要让我们利用STL来记录?后来 ...
- 紫书动规 例题9-10 UVA - 1626 Brackets sequence 区间dp
题目链接: https://vjudge.net/problem/UVA-1626 题意: 题解: dp[i][j]:= i~j需要最少的括号 区间dp: dp[i][j] = min(dp[i][j ...
- UVA 10706 Number Sequence
题意:给出一串那样的数字,很有规律的,总共有2147483647位,然后问你第 n 位上的数字是多少. 思路:具体做法是用两个数组保存上面的数据. 1.[] 数组表示前面所有段的位数,a[i]表示前i ...
最新文章
- Python猜字游戏(用函数)(最新版)
- 存储过程存储函数得简记(转)
- linux虚拟机上离线安装mysql_Linux下离线安装MySQL
- [转载] python cmp函数比较字典_Python 字典(Dictionary) cmp()方法
- Azkaban的Web Server源码探究系列22: 一次性执行execute的提交准备
- @Transactional注解的几个参数--事务传播控制--事务隔离级别--异常与回滚
- 【原】数据分析/数据挖掘/机器学习---- 必读书目
- Python办公自动化——批量发送邮件
- FreeBSD搭建Nginx+Apache24+php56+mysql56手把手一步步的笔记
- 如何隐藏或显示 计算机 桌面图标,如何隐藏电脑桌面图标或文件
- 打开注册表regedit
- spark 集群优化
- Not annotated parameter overrides @NonNullApi parameter
- 【随记】无线网络能替代有线网络吗?
- c#窗体程序未响应问题
- pads layout“生成泪滴”
- python——常用的数学计算公式
- UEStudio中进行文件编码转换
- 2021年底跨平台技术比较和选型指南(也许是最全的)
- jdk1.9的安装与环境配置