题意:

      给你一个栈,里面有n个数,和一个双头队列(空的),每次从栈里拿出一个数据,有三种选择,可以选择丢弃这个数字,也可以放到队头或者队尾,最后问你这个队列你面的最长连续非下降序列的长度...

思路:

      我感觉就是在1025的基础上加强了几个等级,那个题目就是二分贪心求公共子序列,这个题目的细节是用到了1025的思路的,首先我们枚举每一个数,把他当做进队列的第一个数字,那么此时的答案就是 该起点开始的最长费递减子序列 + 该起点开始的最长非递增子序列 - 他们相同的部分.他们相同的部分是的数字肯定是 当前这个数字,那么我们只要找到他俩序列中含有的当前这个数的个数中较小的哪一个减去就行了(相同部分一定是小的是大的子集).值得注意的是我们要倒着枚举数据,减少时间复杂度..


如果没看懂的话我就帮忙回一下1025,正好自己也总结下,dp是自己的弱点,有必要总结..1025 说的是给你n个数(n很大) 求上升子序列...那个题目的思想是 二分 + 贪心(个人感觉 ,有的人认为是 二分 + dp, 随意,dp和贪心相同又不同)开一个数组now[i],记录的是第i个位置最小可以是now[i],对于每一个数num[i]每次我们二分找到num[i],在now[i]中的位置,也就是i,如果这个i>当前长度,那么就更新当前长度,其实这个[i]就是以当前这个数为序列终点的序列的长度,4046上面的那个题目用到的就是在now[i]中再次二分找到now[i]的起始位置,更新的时候我们找的是终止位置,根据这个差我们就找到了重复的num[i]的个数,值得注意一点的就是当前的这个now数组中的数并不是什么子序列的数字,只是单纯的记录某个位置的最小,没有别的意义,光靠这个数组无法输出真正的子序列,但是对于当前时刻当前的num[i],now[i]中连续的num[i]的个数是num[i]为终点的子序列的最后几位数,还有没被别的更新,所以根据now[]中连续的num[i]我们算出的连续num[i].的个数是正确的...



#include<stdio.h>
#include<string.h> #define N 100000 + 500

int
upp[N] ,loww[N] ,now[N];
int
num[N];
int
same[N]; int minn(int x ,int y)
{
return
x < y ? x : y;
} int main ()
{
int
t ,n ,i;
scanf("%d" ,&t);
while(
t--)
{

scanf("%d" ,&n);
for(
i = 1 ;i <= n ;i ++)
scanf("%d" ,&num[i]);
int
low ,up ,mid ,len;
now[1] = num[n] ,len = 1;
same[n] = 1;
for(
i = n - 1 ;i >= 1 ;i --)
{

low = 1 ,up = len;
int
mk = 0;
while(
low <= up)
{

mid = (low + up) >> 1;
if(
num[i] <= now[mid])
{

low = mid + 1;
mk = mid;
}
else
up = mid - 1;
}

mk ++;
if(
mk > len) len ++;
now[mk] = num[i];
loww[i] = mk; low = 1 ,up = len;
mk = 0;
while(
low <= up)
{

mid = (low + up) >> 1;
if(
num[i] < now[mid])
{

low = mid + 1;
mk = mid;
}
else
up = mid - 1;
}

same[i] = loww[i] - mk;
}
now[1] = num[n];
len = 1;
for(
i = n - 1 ;i >= 1 ;i --)
{

low = 1 ,up = len;
int
mk = 0;
while(
low <= up)
{

mid = (low + up) >> 1;
if(
num[i] >= now[mid])
{

low = mid + 1;
mk = mid;
}
else
up = mid - 1;
}

mk++;
if(
mk > len) len ++;
now[mk] = num[i];
upp[i] = mk;
low = 1 ,up = len;
mk = 0;
while(
low <= up)
{

mid = (low + up) >> 1;
if(
num[i] > now[mid])
{

low = mid + 1;
mk = mid;
}
else
up = mid - 1;
}

same[i] = minn(same[i] ,upp[i] - mk);
} int
ans = 0;
for(
i = 1 ;i <= n ;i ++)
if(
ans < loww[i] + upp[i] - same[i])
ans = loww[i] + upp[i] - same[i];
printf("%d\n" ,ans);
}
return
0;
}

hdu4604 不错的子序列问题的更多相关文章

  1. HDU1160:FatMouse's Speed(最长上升子序列,不错的题)

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1160 学的东西还是不深入啊,明明会最长上升子序列,可是还是没有A出这题,反而做的一点思路没有,题意就不多说 ...

  2. hdu4604 Deque(最长上升子序列变形)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4604 题意:一个含有n个数栈,每次取出一个数,可以把这个数放在deque(双向队列)首部,放在尾部,或 ...

  3. {POJ}{3903}{Stock Exchange}{nlogn 最长上升子序列}

    题意:求最长上升子序列,n=100000 思路:O(N^2)铁定超时啊....利用贪心的思想去找答案.利用栈,每次输入数据检查栈,二分查找替换掉最小比他大的数据,这样得到的栈就是更优的.这个题目确实不 ...

  4. HDU 1003 Max Sum && HDU 1231 最大连续子序列 (DP)

    Max Sum Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Sub ...

  5. 2124: 等差子序列 - BZOJ

    Description 给一个1到N的排列{Ai},询问是否存在1<=p1=3),使得Ap1,Ap2,Ap3,…ApLen是一个等差序列. Input 输入的第一行包含一个整数T,表示组数.下接 ...

  6. Lintcode--010(最长上升子序列)

    给定一个整数序列,找到最长上升子序列(LIS),返回LIS的长度.LIS(longestIncreasingSubsequence) 说明: 最长上升子序列的定义: 最长上升子序列问题是在一个无序的给 ...

  7. 从0打卡leetcode之day 3 -- 最大子序列和

    前言 就有要把leetcode的题刷完,每天一道题,每天进步一点点 从零打卡leetcode之day 3 题目描述: 给定一个int类型的数组,求最大子序列的和. 也就是说,从这个数组中截取一个子数组 ...

  8. 动态规划--最长上升子序列(Longest increasing subsequence)

    前面写了最长公共子序列的问题.然后再加上自身对动态规划的理解,真到简单的DP问题很快就解决了.其实只要理解了动态规划的本质,那么再有针对性的去做这方的题目,思路很快就会有了.不错不错~加油 题目描述: ...

  9. 经典递归问题:0,1背包问题 kmp 用遗传算法来解背包问题,hash表,位图法搜索,最长公共子序列

    0,1背包问题:我写笔记风格就是想到哪里写哪里,有很多是旧的也没删除,代码内部可能有很多重复的东西,但是保证能运行出最后效果 '''学点高大上的遗传算法''' '''首先是Np问题的定义: npc:多 ...

随机推荐

  1. kubernets资源预留

    一.  Kubelet Node Allocatable Kubelet Node Allocatable用来为Kube组件和System进程预留资源,从而保证当节点出现满负荷时也能保证Kube和Sy ...

  2. 剑指 Offer 37. 序列化二叉树 + 二叉树的层次遍历

    剑指 Offer 37. 序列化二叉树 Offer_37 题目描述 题目解析 本题主要考察的就是二叉树的层次遍历. 层次遍历时可以根据二叉树的特点将空结点也进栈. 反序列化时同样可以根据层次遍历的思路 ...

  3. 追溯 MySQL Statement Cancellation Timer

    原文 1. 背景 在 jstack 的内容中可以看到以下的 MySQL Statement Cancellation Timer 守护线程, 在业务高峰期的时候会出现大量的这类守护线程, 由此追溯该线 ...

  4. 01----python入门----python安装与初识

    ----python入门----python安装与初识 python是一门编程语言,作为学习python的开始,需要事先搞明白:编程的目的是什么?什么是编程语言?什么是编程? 这是一个很好的开头!但是 ...

  5. 为什么要从 Linux 迁移到 BSD 5

    为什么要从 Linux 迁移到 BSD 5 干净的分离 在 FreeBSD 的设计方式下,不同的组件组合在一起的,处理配置和调优,以及多年来开发和改进的所有工具,使得使用 FreeBSD 是一件很特别 ...

  6. 【python】虚拟环境管理之 virtualenv 、pipenv

    虚拟环境介绍 应用场景 python在安装第三方包时,会被pip安装到/site-package下,如果我们需要同时维护多个python项目,那这些项目都会共用一个python,而真实需求是多个项目之 ...

  7. Java 在PPT中添加文本水印的简易方法(单一/平铺水印)

    [前言] 在PPT幻灯片中,可通过添加形状的方式,来实现类似水印的效果,可添加单一文本水印效果,即在幻灯片中心位置水印以单个文本字样显示,但通过一定方法也可以添加多行(平铺)文本水印效果,即在幻灯片中 ...

  8. hessian简单介绍

    Hessian是基于HTTP的轻量级远程服务解决方案,Hessian像Rmi一样,使用二进制消息进行客户端和服务器端交互.但与其他二进制远程调用技术(例如Rmi)不同的是,它的二进制消息可以移植其他非 ...

  9. 锁与同步器的基础--AQS

    什么是AQS AQS全名AbstractQueueSynchronizer,可以翻译为抽象队列同步器 Abstract--说明该类需要被继承,提供实现的框架和一些必要的功能 事实上,AQS也的确提供了 ...

  10. 云原生的弹性 AI 训练系列之一:基于 AllReduce 的弹性分布式训练实践

    引言 随着模型规模和数据量的不断增大,分布式训练已经成为了工业界主流的 AI 模型训练方式.基于 Kubernetes 的 Kubeflow 项目,能够很好地承载分布式训练的工作负载,业已成为了云原生 ...