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

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

题意:一个含有n个数栈,每次取出一个数,可以把这个数放在deque(双向队列)首部,放在尾部,或者扔掉不管

    但是要保证deque中的数是非递减的。最要求deque中最长能是多少。

思路;对栈中的每个数按照顺序查找其最长非下降子序列,和最长非上升子序列,减掉其公共部分,就得出所求的答案了。

   注意:求其最长非上升子序列的时候只要把所有值去负数,再求其最长非下降子序列就可以了。

    //对LIS的写法应用还是不够灵活,了解还是不够深入,多练。见的多了会的就多了。

AC代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
#define ll long long
const int maxn=1e5+5;

int a[maxn];

int main()
{
    int T,n;
    scanf("%d",&T);
    int len1,len2,same,ans;
    while(T--)
    {
        vector<int>v1;
        vector<int>v2;
        ans=0;
        scanf("%d",&n);
        for(int i=0; i<n; i++)
            scanf("%d",&a[i]);

        for(int i=1; i<=n; i++)
        {
            int b=upper_bound(v1.begin(),v1.end(),a[n-i])-v1.begin();
            int c=lower_bound(v1.begin(),v1.end(),a[n-i])-v1.begin();
            if(b==v1.size()) v1.push_back(a[n-i]);
            else v1[b]=a[n-i];
            len1=b+1;
            same=b-c+1;

            b=upper_bound(v2.begin(),v2.end(),-a[n-i])-v2.begin();
            c=lower_bound(v2.begin(),v2.end(),-a[n-i])-v2.begin();
            if(b==v2.size()) v2.push_back(-a[n-i]);
            else v2[b]=-a[n-i];
            len2=b+1;
            same=min(same,b-c+1);

            ans=max(ans,len1+len2-same);
        }
        printf("%d\n",ans);
    }
    return 0;
}
时间: 2024-10-02 01:19:08

hdu4604 Deque(最长上升子序列变形)的相关文章

HDU 1160 FatMouse&#39;s Speed 动态规划 记录路径的最长上升子序列变形

题目大意:输入数据直到文件结束,每行两个数据 体重M 和 速度V,将其排列得到一个序列,要求为:体重越大 速度越低(相等则不符合条件).求这种序列最长的长度,并输出路径.答案不唯一,输出任意一种就好了. 题目思路:这是个最长上升子序列的问题,我们按W的升序进行排序,若W相等则按V的降序排序.用Pre[]记录当前点的前驱节点,Last记录序列最后一个点,maxn记录最长长度,完成动规后可根据Last和Pre[]输出路径. #include<cstdio> #include<stdio.h&

vijos P1028 最长上升子序列变形题

#include<iostream> #include<cstdio> #include<cstring> #include<map> #include<string> #include<vector> #include<algorithm> using namespace std; bool judge(const string &aa,const string &bb) { for(int i=0;i&

【HDU】5256 序列变换(最长上升子序列变形)

如果a[i]和a[j]想不变,需要满足的条件就是 a[j] - a[i] > j - i 也就是a[i] - i < a[j] - j 比如1 4 2 就不满足,所以1和2之间一定有一个需要改变 所以我们对所有a[i] - i求其最长上升子序列就可以了 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn = 100005; con

poj1159--Palindrome(dp:最长公共子序列变形 + 滚动数组)

Palindrome Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 53414   Accepted: 18449 Description A palindrome is a symmetrical string, that is, a string read identically from left to right as well as from right to left. You are to write a

UVA 10723--Cyborg Genes+最长公共子序列变形

题目链接:点击进入 首先对于长度最短的情况是很容易确定的,只需要用两个字符串的长度和减去他们的最长公共子序列长度.然后比较麻烦的就是合乎要求的字符串的个数,其实我们也可以用类似于最长公共子序列的dp来求. 设dp[i][j]表示str1的前i个字符和str2的前j个字符所得到的满足要求的字符串,则如果str[i]==str[j],则dp[i][j]+=dp[i-1][j-1]; 否则就要根据i,j这两个位置上的最长公共子序列长度进行讨论,具体见代码. 代码如下: #include<iostrea

hdu1243(最长公共子序列变形)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1243 分析:dp[i][j]表示前i个子弹去炸前j个恐怖分子得到的最大分.其实就是最长公共子序列加每个字母值为1,这里每个字母代表的值变化了一下. 状态转移方程:if(s1[i-1]==s2[j-1])dp[nxt][j]=dp[cur][j-1]+val[s1[i-1]];                              else  dp[nxt][j]=max(dp[nxt][j-1]

poj1836--Alignment(dp,最长上升子序列变形)

Alignment Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 13319   Accepted: 4282 Description In the army, a platoon is composed by n soldiers. During the morning inspection, the soldiers are aligned in a straight line in front of the cap

51Nod 1092 回文字符串 | 最长公共子序列变形

求字符串和其逆的最长公共子序列,需要添加的字符数就为长度-最长公共子序列长 #include "stdio.h" #include "string.h" #define maxn 1005 char s[maxn],s1[maxn]; int dp[maxn][maxn]; int main() { int n=0,i,j,len; scanf("%s",s); len=strlen(s); strcpy(s1,s); strrev(s1); f

hdu5773 最长上升子序列变形(附带模板)

先说说最长上升子序列的模板,时间复杂度O(nlogn) 最长上升子序列 #include <iostream> #include <cstdio> #include <cstring> using namespace std; const int N = 41000; int a[N],p; //a[i] 原始数据 int d[N]; //d[i] 长度为i的递增子序列的最小值 int BinSearch(int key, int low, int high)//二分查

poj 1952 BUY LOW, BUY LOWER[最长单调子序列变形]

题目:poj 1952 BUY LOW, BUY LOWER 题意:给出一个序列,先求最长单调递减子序列,然后求在子序列最长的情况下,不同的长度都为最长的的子序列的个数.(比如3,2,1和3,2,1属于相同,只能算一个) 分析:首先用一个dp[i]表示到当前i点的最长子序列的长度 用dp2[i]表示最长为dp[i]的子序列的个数 然后dp[i] = max(dp[j])+1 (1<=j /************************************ Problem: 1952 Use