【hdu】4521 小明系列问题——小明序列【LIS变种】

时间:2023-01-14 19:31:32

题意:

求最长上升子序列,其中子序列中相邻的两个数的下标差要超过k

题解:

英语不好读题都读不好 之前看成了子序列中相邻的两个数的大小要超过k怎么都做不对

后来lower_bound写成了upper_bound

记住了最长上升子序列如果要求严格上升的话就是lower_bound 可以相等的话就是upper_bound

子序列中相邻的两个数的下标要超过k,要想满足这个条件我们可以按下面的思路想:

首先nlogn的LIS是毫无疑问的,然后再这个算法中,我们每次二分找到当前数的位置,如果数组中的数比当前数大的话就更新数组

所以我们可以稍微改一下上述步骤,当我们二分计算当前数的位置时,只是把当前数应该在数组中的位置保存下来,当前只更新在i-k之前的那个数,

这样我们就可以保证每次二分查找时,数组中的所有数的下标都比当前的下标少至少k

质体还有的解法是线段树 我没怎么考虑 有兴趣可以去看看

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int inf=0x3f3f3f3f;
const int N=1e5+10;
int d[N],a[N],b[N];
int main()
{//freopen("C:\\Users\\Administrator\\Desktop\\input.txt","r",stdin);
    int n,i,r,k;
    while(scanf("%d%d",&n,&k)!=EOF){
        for(i=0;i<=n;i++)d[i]=inf;
        for(i=0;i<n;i++)scanf("%d",&a[i]);
        r=0;
        for(i=0;i<n;i++){
            int x=lower_bound(d,d+r,a[i])-d;
            b[i]=x;
            if(x==r) r++;
            int j=i-k;
            if(j>=0&&d[b[j]]>a[j])d[b[j]]=a[j];
        }
        printf("%d\n",r);
    }
    return 0;
}