LIS升级版-Deque HDU

来源:互联网 发布:python实现svm 编辑:程序博客网 时间:2024/06/05 02:57

https://vjudge.net/problem/HDU-4604
给定一排数和一个 双头队列。
可以往头插还可以往后插的,问你最大得到的 非递减队列的长度。
经过分析,枚举每个点作为开头的 最大非严格递增和 最大非严格递减子序列,然后相加 减去他们 中重叠的数。
重叠的数是这样计算的。分别计算一个数在 两个数列中的数量,然后取最大的那一个

前天才看懂代码的意思,被一个地方卡了。
首先,
a=upper_bound(a,a+n,x)-a;
b=lower_bound(a,a+n,x)-a;
1 a-b+2 和 upper_bound()-lower_bound()其实是一样的。。
只是写法不同,都是计算那个x在a[]中的数量。。
2 别人一句话就给我说明白了。lis本来是求的dp[]是以i为末尾的长度。如果反响求,并且递增改成递减,就可以求以头为长度的了。
并且要 注意 差别,递增和非递降有点差别,
如果用的是a,即每次插入都是在第一个大于他的数,那就是非递降啊(相同的数得以保存,数组中假设有一个 1 2 3 ,那么再插入一个3,还是可以插在最后面的,哈哈两个3 了如果这样。)
但是如果是用b呢,那么就还是得到 12 3 ,还是一个3,、
就这点不一样。
4 另外我感觉还是应该锻炼自己的思考能力,多思考基本的dp结构。
这种题可以加强对lis的理解。
6 我第一次吧name初始化为1,然后求最大的也过了。突然我发现。
两个数列中 同一个数的存在个数肯定是相同的。
求最大的和最小的都是一样的。除非一个 正常递增,一个非严格递减,然后出现不同的情况,不过这种情况用本题的代码也可以算。
如果求最小的就初始化为0x3f3fl

第一次反转,求的是以一个点为首的下降子序列(但是位置不是以前的位置,即第一个数其实是原数组中倒数第一个数的)
在反转的基础上又进行了 取负值,求的才是以这个数的上升,不过也是相反的位置,和上一个一个,故进行加减不会造成损失

#include <bits/stdc++.h>using namespace std;/*先求一个 递降(非标准递降,就是不递升)然后再求一次递升,(非标准递升,就是不递降)本来lis计算的是为最后的数,倒着计算就是为头的数。该球递降的求递升,该求递升的求递降二者相反,但由于这道题二者都需要计算,所以就不用了 qwq*/const int maxn=100006;int a[maxn];int num[maxn];int n;int solve(int dp[]){   vector<int>q;//设置一个队列来储存这个序列.    for(int i=0;i<n;i++)     {    int a1=upper_bound(q.begin(),q.end(),a[i])-q.begin();//用来计算第一个比他大的          int b1=lower_bound(q.begin(),q.end(),a[i])-q.begin();       if(a1==q.size())       {   q.push_back(a[i]);           dp[i]=q.size();       }       else       {   q[a1]=a[i];//把第一个大于的数给换掉           dp[i]=a1+1;       }        num[i]=min(num[i],a1-b1+1);//或者初始为1,求最大     }    return 0;}int main(){  std::ios::sync_with_stdio(false);    int dp1[maxn];    int dp2[maxn];    int t;   cin>>t;   while(t--)   {  memset(dp1,0,sizeof(dp1));      memset(dp2,0,sizeof(dp2));      memset(num,0,sizeof(num));      memset(a,0,sizeof(a));        scanf("%d",&n);        for(int i=0;i<n;i++)            num[i]=0x3f3f3f3f;//为什么要设置成0呢,因为最少一个数也是0啊。。      for(int i=0;i<n;i++)          scanf("%d",&a[i]);       for(int i=0;i<n;i++)      reverse(a,a+n);       solve(dp1);       for(int i=0;i<n;i++)        a[i]=-a[i];       solve(dp2);       int all=0;       for(int i=0;i<n;i++)      all=max(all,dp1[i]+dp2[i]-num[i]);       printf("%d\n",all);   }    return 0;}
0 0
原创粉丝点击