51Nod 2506 最长高地 c/c++题解

题目描述

小b有一个长度为n的数组A。
小b认为,如果A的一个区间[l,r]满足r-l>=2,且存在l<p<r使得A[l]<A[l+1]<… <A[p]>A[p+1]>…>A[r],则[l,r]为一个高地。
求A中的最长高地的长度。
输入
第一行输入一个非负整数n,表示A数组长度;
第二行输入n个数,表示A数组的元素,以空格隔开;
其中0≤n≤10000,A中任意元素A[i]满足0≤A[i]≤10000.
输出
输出一个数,表示最长高地的长度
输入样例
7
2 1 4 7 3 2 5
输出样例
5

题解:

解法1(我一最开始的解法,我看见时限有2s,我就直接用的O(n3),但是超时了3个点,说明1e15的数据规模2s过不了): 就是开两重循环枚举所有的序列l->r,然后O(n)判断序列l->r,是否为先递增再递减(注意必须为先增再减,也就是说不可以一直增or一直减)。(如果这种上面说的看不懂的话,直接看下面的解法)
解法2: 枚举从2->(n-1)的每个元素i,假设i对应的a[i]就是高地的最上方(序列元素的最大值),然后递减的看左边最多能达到多远,记录下left(初始化为i),再递增的来看右边最多能达到多远,记录下right(初始化为i),最后记录下最大高地的长度:max(max_length,right-left+1)。

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <cstring>
#include <string>
#include <algorithm>
#include <vector>
#include <deque>
#include <list>
#include <utility>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <bitset>
#include <iterator>
using namespace std;

typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll  INF = 0x3f3f3f3f3f3f3f3f;
const double PI = acos(-1.0);
const double E = exp(1.0);
const int MOD = 1e9+7;
const int MAX = 1e4+5;
int n;
int a[MAX];

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    while(cin >> n)
    {
        for(int i = 1; i <= n; i++)
        {
            cin >> a[i];
        }
        int max_len = 0;
        /* 超时
        for(int i = 1; i <= n-2; i++)
        {
            for(int j = i+2; j <= n; j++)
            {
                int max_v = -inf;
                int index = -1;
                for(int k = i; k <= j; k++)
                {
                    // 从i-j中找到最大的值
                    if(a[k] > max_v)
                    {
                        max_v = a[k];
                        index = k;
                    }
                }
                bool flag = true;// 判断是否从i-index递增,index-j递减
                for(int k = i+1; k <= index; k++)
                {
                    if(a[k] <= a[k-1])
                    {
                        flag = false;
                        break;
                    }
                }
                for(int k = index+1; k <= j; k++)
                {
                    if(a[k] >= a[k-1])
                    {
                        flag = false;
                        break;
                    }
                }
                if(flag && index != i && index != j)
                {
                    // 说明i-j的序列是先增再减的
                    if(j-i+1 > max_len)
                    {
                        max_len = j-i+1;
                        flag = true;
                    }
                }
            }
        }*/

        for(int i = 2; i < n; i++)
        {
            int left = i;
            for(int j = i; j > 1; j--)
            {
                if(a[j] > a[j-1])
                    left = j - 1;
                else
                    break;
            }

            int right = i;
            for(int j = i; j < n; j++)
            {
                if(a[j+1] < a[j])
                    right = j + 1;
                else
                    break;
            }
            max_len = max(max_len,right-left+1);
            //printf("i = %d left = %d right = %d\n",i,left,right);
        }
        cout << max_len << endl;
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值