这道题的意思是让我们求一个上升子序列  + 一个下降字序列,且两边的长度是相等的,由于用正常的 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相关推荐

  1. uva 10534——Wavio Sequence

    题意:给定一个序列,求一个最长的序列,使得他的前半部分是递增的,而后半部分是递减的,且两部分的长度一样. 思路:经典的LIS问题,和openjudge登山问题一样,前后各扫一遍,找到前置和倒置的LIS ...

  2. UVA 10534 Wavio Sequence DP LIS

    题意:求一个波浪子序列,就是是前一半是上升子序列,后一半是下降子序列(子序列的长度必须为奇数). 分别从左右两个方向求LIS,然后在统计最大值就行了 //#pragma comment(linker, ...

  3. 【UVa】Wavio Sequence(dp)

    http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&p ...

  4. UVA10534 Wavio Sequence【LIS+DP】

    Wavio is a sequence of integers. It has some interesting properties. • Wavio is of odd length i.e. L ...

  5. uva 1626 - Brackets sequence

    // // main.cpp // uva 1626 - Brackets sequence/*这一题应该是经典的矩阵类似问题.显然 需要使用两个变量来表示最终的结果.设 dp[i][j]表示第i个位 ...

  6. UVA - 1626 Brackets sequence

    题目链接 给你一个括号序列,输出一个前后括号都匹配的补全序列,且补的字符尽量少. 对一个串s来说,只会有两种情况:1.(t)或[t]转移到t 2.有两个字符,分段转移.为了保证是最小值,一定要考虑情况 ...

  7. UVA - 1594 Ducci Sequence

    /*做这题时的心路历程其实挺有趣的一开始看到说Ducci序列最终要么全0,要么循环,我在想:要怎么判断循环呢?是不是还得记录下循环节什么的?是该用数组记录循环节吗?还是想要让我们利用STL来记录?后来 ...

  8. 紫书动规 例题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 ...

  9. UVA 10706 Number Sequence

    题意:给出一串那样的数字,很有规律的,总共有2147483647位,然后问你第 n 位上的数字是多少. 思路:具体做法是用两个数组保存上面的数据. 1.[] 数组表示前面所有段的位数,a[i]表示前i ...

最新文章

  1. Python猜字游戏(用函数)(最新版)
  2. 存储过程存储函数得简记(转)
  3. linux虚拟机上离线安装mysql_Linux下离线安装MySQL
  4. [转载] python cmp函数比较字典_Python 字典(Dictionary) cmp()方法
  5. Azkaban的Web Server源码探究系列22: 一次性执行execute的提交准备
  6. @Transactional注解的几个参数--事务传播控制--事务隔离级别--异常与回滚
  7. 【原】数据分析/数据挖掘/机器学习---- 必读书目
  8. Python办公自动化——批量发送邮件
  9. FreeBSD搭建Nginx+Apache24+php56+mysql56手把手一步步的笔记
  10. 如何隐藏或显示 计算机 桌面图标,如何隐藏电脑桌面图标或文件
  11. 打开注册表regedit
  12. spark 集群优化
  13. Not annotated parameter overrides @NonNullApi parameter
  14. 【随记】无线网络能替代有线网络吗?
  15. c#窗体程序未响应问题
  16. pads layout“生成泪滴”
  17. python——常用的数学计算公式
  18. UEStudio中进行文件编码转换
  19. 2021年底跨平台技术比较和选型指南(也许是最全的)
  20. jdk1.9的安装与环境配置

热门文章

  1. Java字节码进制转换
  2. redis的通用命令 || redis持久化机制:(RDB  ||  AOF)
  3. 百度网盘javascript加速视频播放速度
  4. Unity学习笔记3 简易2D横版RPG游戏制作(三)
  5. Mac 技术篇-设置Finder文件管理显示文件路径
  6. Mac 技术篇-mac远程桌面直接连接windows系统,微软官方工具Microsoft Remote Desktop远程桌面工具安装与使用
  7. python opencv 图像网络传输
  8. C# 学习笔记(5) 继承
  9. 智能门锁中CPU卡加密
  10. CTFshow 命令执行 web121