算法:动态规划 洛谷 P8776 [蓝桥杯 2022 省 A] 最长不下降子序列

思路:首先,这题你得先会(nlogn)复杂度的求最长不下降子序列方法。我们可以直接让k个数从下标为1开始,滑动到末端,这k个数就不用看它,因为我们把他设置成k个数后面的数,所以答案先加上k,然后我们看预处理每一个数从他开始(包括这个数)后面的最长不下降子序列,把长度放入b数组中,这样我们答案就是k加上b【k+1】,然后我们看k前面的数,k前面的数不是让答案加上前面的最长不下降子序列,因为此时我们有条件限制,因为我们要让前面的数的子序列保证都小于a【k+1】这个数,这个就直接看end数组(end数组你得学前面说的nlogn算法才知道)大于他的数的位置,直接得出答案。然后k个数滑动窗口滑一遍就看哪个最大,就是答案

代码:

#include
#define ll long long
using namespace std;
ll n,k,i,j,ans;
vectora(100005),b(100005),en,en2;//en是预处理的end数组,en2是k前面数的end数组,b数组用来存i(包含i)开头往后面的最长不下降子序列
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin>>n>>k;
    for(i=1;i<=n;i++){
        cin>>a[i];
    }
    for(i=n;i>0;i--){
        if(upper_bound(en.begin(),en.end(),-a[i])==en.end()){//这里我让end数组存入负数,来反向处理
            en.push_back(-a[i]);
            b[i]=en.size();
        }else{
            b[i]=upper_bound(en.begin(),en.end(),-a[i])-en.begin()+1;
            en[upper_bound(en.begin(),en.end(),-a[i])-en.begin()]=-a[i];   
        }
    }
    ans=k+b[k+1];//这种情况是k前面没数的情况
    j=k+2;
    i=1;
    for(;j<=n;j++,i++){
        if(upper_bound(en2.begin(),en2.end(),a[i])==en2.end()){
            en2.push_back(a[i]);
        }else{
            en2[upper_bound(en2.begin(),en2.end(),a[i])-en2.begin()]=a[i];   
        }   
        if(upper_bound(en2.begin(),en2.end(),a[j])==en2.end()){
            ll x=en2.size()+b[j]+k;
            ans=max(ans,x);
        }else{
            ll x=upper_bound(en2.begin(),en2.end(),a[j])-en2.begin()+b[j]+k;
            ans=max(ans,x);
        }
    }
    cout<

你可能感兴趣的:(算法,动态规划,蓝桥杯)