重启系统(等级考试4级 2021-03 T4)

 

 这道题如果没有一次重启系统的机会就相当于两个最长不下降子序列加在一起。

所以只需要改亿点点即可

把dp分为 dpleft 和 dpright

最长不下降子序列程序:最长上升子序列 II 时间复杂度(nlogn) - 王浩泽 - 博客园 (cnblogs.com)

#include<bits/stdc++.h>using namespace std;const int N=1e5;const int inf=1e9;int main(){    int a[N],dp[N],n;        cin>>n;    for(int i=1;i<=n;i++) scanf("%d",&a[i]);        int len=0;    for(int i=1;i<=n;i++)    {        int l=0,r=len+1;        while(l+1!=r)        {            int m=l+r>>1;            if(dp[m]<a[i])            {                l=m;            }            else            {                r=m;            }        }        dp[r]=a[i];        len=max(len,r);    }        cout<<len;    return 0;}

合在一起即可(还要注意亿点细节)

like  

for(int x = 1; x <= n; x++){
        ans = max(ans, dpleft[x] + dpright[x + 1]);
    }

这里的dpleft[x]应该加上dpright[x+1] 如果用x 和 x 的话    x可能会被用两次。

dpleft 和 dpright  都应该初始化为1

在这里给大家推荐一个函数让后面原来倒着算的最长下降子序列 变成正着算的最长上升子序列。
reverse(a + 1, a + n + 1);

之后再拼拼凑凑变成前一段程序:

scanf("%d",&n);
    for (int i = 1;i <= n;i++){
        scanf("%d",&a[i]);
        dpright[i] = dpleft[i] = 1;
    }
    reverse(a + 1, a + n + 1);
    for (int i = 1;i <= n;i++){
        for (int j = 1; j < i;j++){
            if(a[i] >= a[j]){
                dpleft[i] = max(dpleft[i],dpleft[j] +1);
            }
        }
    }

    for (int i = 2;i <= n;i++){
        dpleft[i] = max(dpleft[i - 1], dpleft[i]);
    }
    for(int i = n - 1; i >= 1; i--){
        for(int j = n; j > i; j--){
            if(a[i] <= a[j]){
                dpright[i] = max(dpright[i], dpright[j] + 1);
            }
        }
    }

最后再找亿下最大值塞入ans中最后输出即可:

for(int i = n - 1; i >= 1; i--){
        dpright[i] = max(dpright[i], dpright[i + 1]);
    }
    int ans = 0;
    for(int x = 1; x <= n; x++){
        ans = max(ans, dpleft[x] + dpright[x + 1]);
    }
    printf("%d\n", ans);
    return 0;

   

 

 

完整代码:

#include <bits/stdc++.h>
using namespace std;
   
int dpleft[10005],dpright[10005], a[10005]; 
int n;
   
int main(){
    scanf("%d",&n);
    for (int i = 1;i <= n;i++){
        scanf("%d",&a[i]);
        dpright[i] = dpleft[i] = 1;
    }
    reverse(a + 1, a + n + 1);
    for (int i = 1;i <= n;i++){
        for (int j = 1; j < i;j++){
            if(a[i] >= a[j]){
                dpleft[i] = max(dpleft[i],dpleft[j] +1);
            }
        }
    }

    for (int i = 2;i <= n;i++){
        dpleft[i] = max(dpleft[i - 1], dpleft[i]);
    }
    for(int i = n - 1; i >= 1; i--){
        for(int j = n; j > i; j--){
            if(a[i] <= a[j]){
                dpright[i] = max(dpright[i], dpright[j] + 1);
            }
        }
    }
    for(int i = n - 1; i >= 1; i--){
        dpright[i] = max(dpright[i], dpright[i + 1]);
    }
    int ans = 0;
    for(int x = 1; x <= n; x++){
        ans = max(ans, dpleft[x] + dpright[x + 1]);
    }
    printf("%d\n", ans);
    return 0;
} 
posted @ 2022-03-06 15:45  王浩泽  阅读(196)  评论(6编辑  收藏  举报