题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4604

这个题解有点问题,暂时没时间改,还是参考别人的吧

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <queue>
#include <vector>
#define maxn 100500
using namespace std; const int INF = 0x3f3f3f; int a[maxn];
int s1[maxn],s2[maxn];
int ans;
int n; int search_lower_bound(int l,int h,int m){
if(l == h) return l;
int mid = (l + h)/;
if(s1[mid] <= m) return search_lower_bound(mid+,h,m);
else return search_lower_bound(l,mid,m);
}
int search_upper_bound(int l,int h,int m){
if(l == h) return l;
int mid = (l + h)/;
if(s2[mid] >= m) return search_upper_bound(mid+,h,m);
else return search_upper_bound(l,mid,m);
} int main()
{
// if(freopen("input.txt","r",stdin)== NULL) {printf("Error\n"); exit(0);} int T;
cin>>T;
while(T--){
cin>>n;
for(int i=;i<n;i++) scanf("%d",&a[i]);
for(int i=;i<=n/;i++){
int temp;
temp = a[n-i-];
a[n-i-] = a[i];
a[i] = temp;
}
s1[] = s2[] = a[];
int rear1 = ,rear2 = ;
ans = ;
for(int i=;i<n;i++){
int temp1,temp2; if(s1[rear1] < a[i]) temp1 = ++rear1;
else{
temp1 = search_lower_bound(,rear1,a[i]);
if(s1[temp1] == a[i]){
for(int i=++rear1;i>temp1;i--) s1[i] = s1[i-];
temp1++; // printf("&&&&&& %d\n",rear1);
}
}
s1[temp1] = a[i]; if(s2[rear2] > a[i]) temp2 = ++rear2;
else{
temp2 = search_upper_bound(,rear2,a[i]);
/*if(s2[temp2] == a[i]){
for(int i=++rear2;i>temp2;i--) s2[i] = s2[i-1];
temp2++; printf("****** %d\n",rear2);
}*/
}
s2[temp2] = a[i];
ans = max(ans,temp1+temp2+);
}
cout<<ans<<endl;
}
}

 这题虽然过了,但存在一个问题。是数据弱了点。正确的思路:

(引用)

考虑题目的一个简化版本:使双端队列单调上升。对于序列A和队列Q,找到队列中最早出现的数字Ax,则Ax将Q分成的两个部分分别是原序列中以Ax开始的最长上升和最长下降序列,答案即为这两者之和的最大值。而对于本题,由于存在相同元素,所以只要找到以Ax 为起点的最长不下降序列和最长不上升序列的和,然后减去两个里面出现Ax次数的最小值即可。

我忽略了下降中的元素可重复,应该要考虑,在减去两个里面都存在的Ax重复次数;

所以有了大神的思路写出全新的代码:

 #include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <queue>
#include <vector>
#define maxn 105000
using namespace std; const int INF = 0x3f3f3f; int d1[maxn],d3[maxn];
int g1[maxn],g2[maxn];
int a[maxn],b[maxn];
int n; int main()
{
//if(freopen("input.txt","r",stdin)== NULL) {printf("Error\n"); exit(0);} int T;
cin>>T;
while(T--){
cin>>n;
for(int i=n-;i>=;i--){
scanf("%d",&a[i]);
b[i] = -a[i];
}
for(int i=;i<=n;i++){
g1[i] = INF;
g2[i] = INF;
}
int ans = ;
for(int i=;i<n;i++){
int k1 = upper_bound(g1+,g1+n+,a[i]) - g1;
int k2 = upper_bound(g2+,g2+n+,b[i]) - g2;
int k3 = lower_bound(g2+,g2+n+,b[i]) - g2;
g1[k1] = a[i];
g2[k2] = b[i];
d1[i] = k1;
d3[i] = k3;
ans = max(ans,d1[i] + d3[i] - );
}
printf("%d\n",ans);
}
}

这才是正确的方法,太精妙了。

lower_bound()是binary_search()的特殊形式. 此函数搜索给定的序列[first, end)中val可插入的第一个位置; 或者说, 它返回序列中遇到的第一个不小于val的元素的迭代器, 如果所有元素都小于val则返回“end”. 从函数要求待搜索序列是有序的.

lower_bound()的返回值乃是一个指向val可以安全插入的位置的迭代器. 在比较函数f被指定之前, 默认使用<操作符进行排序.

而upper_bound()是则是允许重复;

求最长下降就把a[] 变为相反数 b[],求b[]的最长上升子序列;

 

hdu 4604 Deque(最长上升与下降子序列-能够重复)的更多相关文章

  1. HDU 4604 deque 最长上升子序列

    枚举每个位置,求以num[i]为起点的最长不下降子序列和以num[i]为结尾的最长不递增子序列. 并且把相同值的个数统计一下,最后要减去算重复了的. 比如: 1 9 4 4 2 2 2 3 3 3 7 ...

  2. HDU 4604 Deque(最长上升子序)

    题目链接 本来就对N*log(N)算法不大会....然后各种跪了,求出最长不下降+最长不上升-最少相同元素.求相同元素,用二分求上界搞的.代码里4个二分.... #include <cstdio ...

  3. 最长非降/下降子序列问题(DP)(待续...)

    注意:抽象成以下描述即为最长非降/下降子序列问题(一维状态) 问题描述:在一个无序的序列a1,a2,a3,a4…an里,找到一个最长的序列满足:(不要求连续) ai<=aj<=ak…< ...

  4. hdu 4604 Deque(最长不下降子序列)

    从后向前对已搜点做两遍LIS(最长不下降子序列),分别求出已搜点的最长递增.递减子序列长度.这样一直搜到第一个点,就得到了整个序列的最长递增.递减子序列的长度,即最长递减子序列在前,最长递增子序列在后 ...

  5. HDU 4604 Deque 最长子序列

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4604 Deque Time Limit: 4000/2000 MS (Java/Others)     ...

  6. HDU 4604 Deque 二分最长上升子序列

    题目大意就是给一个deque 然后有n个数,依次进行操作,每种操作,你可以把这个数放在deque首部,也可以放在尾部,也可以扔掉不管,但是要保证deque中的数是非递减的.最要求deque中最长能是多 ...

  7. hdu 4604 Deque

    http://acm.hdu.edu.cn/showproblem.php?pid=4604 将原数组根据其大小关系处理后 使其大小全在10^5内 处理后为 a1,a2,a3.....an 最优deq ...

  8. Longest Ordered Subsequence POJ - 2533 dp 最长上升/不下降 子序列

    #include<iostream> using namespace std ; ; int f[N]; int a[N]; int n; int main() { cin>> ...

  9. HDU 6357.Hills And Valleys-字符串非严格递增子序列(LIS最长非下降子序列)+动态规划(区间翻转l,r找最长非递减子序列),好题哇 (2018 Multi-University Training Contest 5 1008)

    6357. Hills And Valleys 自己感觉这是个好题,应该是经典题目,所以半路选手补了这道字符串的动态规划题目. 题意就是给你一个串,翻转任意区间一次,求最长的非下降子序列. 一看题面写 ...

随机推荐

  1. Kettle的集群排序 2——(基于Windows)

    5.使用kettle集群模式对相关的数据进行排序 既然,基于Carte服务程序所搭建的集群已经在Spoon中设定好了, 可以首先,先来启动四个节点: "以管理员身份运行"打开 四个 ...

  2. 如何清除xcode里面的mobileprovision文件

    通过终端进行删除 首先cd到目录”~/Library/MobileDevice/Provisioning\ Profiles” cd ~/Library/MobileDevice/Provisioni ...

  3. 1.swt/rap学习源码网址

    1.rap使用JS/ RAP加载JS http://download.eclipse.org/rt/rap/doc/2.3/guide/reference/jsdoc/symbols/rap.html ...

  4. 使用Eclipse搭建C/C++开发环境(转)

    使用Eclipse搭建C/C++开发环境  文章出自:http://www.cnblogs.com/liuxianan/archive/2013/01/15/2861196.html 说明:网上有很多 ...

  5. photoshop cc 版本安装失败解决办法

    好久没有碰ps,看了下在ps版本都到cc了.忍不住也想尝试最新版本,但是安装出现了很多问题,导致我花了很多时间才搞定,现在分享给大家几点经验吧. Exit Code: Please see speci ...

  6. 《JavaScript高级程序设计 第3版》-学习笔记-1

    P1-P30页 1.<script>标签的属性 async:async(html)  | async="async"(xhtml),表示立即下载脚本,但不马上执行(执行 ...

  7. 在apache上报错“The _imaging C module is not installed”

    我的环境是python2.7.8.django1.6.4.apache2.2. 问题:在django自带的runserver环境下没有任何报错,但是配置在apache上出现了 “The _imagin ...

  8. 怎么用notepad配置来运行C语音环境

    想要运行C语言,我们可以用notepad软件来进行编辑,那么怎么用notepad 配置运行c语言开发环境呢? Notepad++是一款很好的编辑器,可以用来开发很多的工具,具体大家请看下文给大家详细讲 ...

  9. bzoj3140: [Hnoi2013]消毒

    Description 最近在生物实验室工作的小T遇到了大麻烦. 由于实验室最近升级的缘故,他的分格实验皿是一个长方体,其尺寸为a*b*c,a.b.c 均为正整数.为了实验的方便,它被划分为a*b*c ...

  10. NSValue NSNumber NSData类

    NSValue NSNumber NSData类 步骤1 NSValue 我们先看看NSValue能做什么: 一个NSValue对象是用来存储一个C或者Objective-C数据的简单容器.它可以保存 ...