题解 P1091 【合唱队形】

思路:分别求出单调上升和单调下降的序列长度,然后直接求出答案。

#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
const int N=105;
int n,top,ans,a[N],s[N],f[3][N];
int main()
{
    scanf("%d", &n);
    for(int i=1; i<=n; i++)
        scanf("%d", &a[i]);
    //单调上升 
    for(int i=1; i<=n; i++)
    {
        if(a[i] > s[top])//如果可以保持单调性就插入栈 
        {
            s[++top] = a[i];
            f[0][i] = top;
        }else //否则寻找栈里的数替换 
        {
            int L = 1,R = top;
            while(L < R)//二分求出要替换的数,
            {
                int mid = (L + R) / 2;
                if(s[mid] < a[i]) L = mid + 1;else R = mid;
            }
            s[R] = a[i];//R为要替换数的位置 
            f[0][i] = top;//记录下栈的长度 
        }
    }
    top = 0;
    memset(s,0,sizeof(s));
    //单调下降,操作类似于单调上升 
    for(int i=n; i>=1; i--)
    {
        if(a[i] > s[top])
        {
            s[++top] = a[i];
            f[1][i] = top;
        }else
        {
            int L = 1,R = top;
            while(L < R)
            {
                int mid = (L + R) / 2;
                if(s[mid] < a[i]) L = mid+1;else R = mid;
            }
            s[R] = a[i];
            f[1][i] = top;
        }
    }
    for(int i=1; i<=n; i++)
        ans = max(ans, f[0][i] + f[1][i] - 1);//答案为单调上升加上单调下降再减去多加的一个 
    printf("%d", n - ans);//减去留在队列里的数字即为答案 
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/N-S-P/p/10802062.html