1. 程式人生 > 其它 >2021.7.23 刷題記錄

2021.7.23 刷題記錄

AcWing 896 最長上升子序列II

#include <iostream>
#include <cstdio>

using namespace std;

const int N = 1e5+5;

int n;
int h[N];
int d[N]; //d[i]: 表示長度為i的遞增序列的末尾的最小值, 一定遞增
int len = 0;


int main()
{
    scanf("%d", &n);
    for(int i = 0; i < n; ++ i)
    {
        scanf("%d", h+i);
    }
    // d[0] = -INF;
    for(int i = 0; i < n; ++ i)
    {
        //尋找大於等於h[i]的最小的數
        int l = 1, r = len+1; //l==r==len+1表示拓展新的長度
        while(l < r)
        {
            int mid = l+r>>1;
            if(d[mid] >= h[i])
            {
                r = mid;
            }
            else
            {
                l = mid+1;
            }
        }
        d[l] = h[i];
        len = max(len, l);
    }
    printf("%d\n", len);
    return 0;
}

AcWing 482 合唱隊形

#include <iostream>
#include <cstdio>

using namespace std;

const int N = 105;

int n;
int h[N];
int dp[N]; //dp[i]: 以h[i]結尾的上升子序列最大長度
int rdp[N]; //從右往左看的dp

int main()
{
    scanf("%d", &n);
    for(int i = 1; i <= n; ++ i)
    {
        scanf("%d", h+i);
    }
    dp[1] = 1;
    for(int i = 2; i <= n; ++ i)
    {
        dp[i] = 1;
        for(int j = 1; j < i; ++ j)
        {
            if(h[i] > h[j])
            {
                dp[i] = max(dp[i], dp[j]+1);
            }
        }
    }
    rdp[n] = 1;
    for(int i = n-1; i >= 1; -- i)
    {
        rdp[i] = 1;
        for(int j = n; j > i; -- j)
        {
            if(h[i] > h[j])
            {
                rdp[i] = max(rdp[i], rdp[j]+1);
            }
        }
    }
    int ans = 0;
    for(int i = 1; i <= n; ++ i)
    {
        ans = max(ans, dp[i]+rdp[i]-1);
    }
    printf("%d\n", n-ans);
    return 0;
}