【枚举+优化】【队列操作】【RMQ】奶牛派对 tahort.pas/c/cpp

奶牛排队 (tahort)

Problem:       tahort.pas/c/cpp
Input:       tahort.in
Output:       tahort.out
Memory Limit:   128 MB
Time Limit:      1 sec

【 问题描述】

奶牛在熊大妈的带领下排成了一条直队。  

显然,不同的奶牛身高不一定相同……

现在,奶牛们想知道,如果找出一些连续的奶牛,要求最左边的奶牛A是最矮的,最右边的B是最高的,且B高于A奶牛,中间如果存在奶牛,则身高不能和A、B奶牛相同。问这样的奶牛最多会有多少头?

从左到右给出奶牛的身高,请告诉它们符合条件的最多的奶牛数(答案可能是0,2,但不会是1)。

【输入】

     第一行一个数N (2≤N≤l00000),表示奶牛的头数。

    接下来N个数,每行一个数,从上到下表示从左到右奶牛的身高(1≤身高≤ maxlongint)。

【输出】

     第一行,表示最多奶牛数。

【样例】

  Tahort.in

  5

  1

  2

  3

  4

  1

  Tahort.out

  4

【样例解析】

     取第1头到第4头奶牛,满足条件且为最多。

 

 

 

 

 

先说说最朴素的方法,谁都可以想得到,枚举左界 i ,枚举右界 j ,在从 i -> j 用 k 来枚举判断,当然这是接近O(N3)的算法了,就这题的数据O(N2)都过不了,更别说O(N3)了。。。当然朴素可以拿来对拍,然后可以放心大胆去优化,可以保证正确性

那O(N3)的算法就只能对拍的了吗?我们也可以优化!既然左界是最小的,那么后面的就不可能比它更小或相等,所以我们只需要在枚举 j 那里加一句,判断是否 j 那里的数比 i 那里的数还小或者相等,如果成立,那显然后面就没必要再找下去了,所以马上break,就只需要加这一句话,就能从过3组变成过9组!!!我上午以为这个优化不大,所以就又写了队列优化,维护首尾指针,结果没有优化到位,还是也只过了9组。。。。。

后来看数据,第9组有点坑。。。是锯齿状(100000,1,99999,2,99998,3,99997,4,......)

所以我们可以改成倒序枚举就可以全过了。

这里先给出 O(N3)枚举+优化 的代码

/*
C++ Code  枚举+优化
http://oijzh.cnblogs.com
By jiangzh
*/
#include<cstdio>
#define MAXN 100010
#define max(a,b) ((a)>(b)?(a):(b))

int n,a[MAXN];
int ans=0;

void init()
{
    freopen("Tahort.in","r",stdin);
    freopen("Tahort.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
}

void work()
{
    bool flag;
    for(int i=n;i>1;i--)
    {
        for(int j=i-1;j>=1;j--)
        {
            if(a[i]<=a[j])break;//需要满足  a[i]<a[j]
            flag=true;
            for(int k=j+1;k<i;k++)
                if(a[k]<=a[j] || a[k]>=a[i]) {flag=false;break;}//需要满足 a[k]>a[i]  a[k]<a[j]
            if(flag) ans=max(ans,i-j+1);
            if(ans==n) {printf("%d",ans);return;}
        }
    }
    printf("%d",ans);
}

int main()
{
    init();
    work();
    return 0;
}

  

 

 

 

 

至于我上午写的队列优化,是我上午历经与朴素程序N+次对拍才改出来的,不过也只能优化到90分,后面也没优化到100分,过程也不好解释,下面给出代码,尽力看吧

/*
C++ Code
http://oijzh.cnblogs.com
By jiangzh
队列维护
*/
#include<cstdio>
#define MAXN 100010
#define max(a,b) ((a)>(b)?(a):(b))

int n,a[MAXN];
int ans=0;

void init()
{
    freopen("Tahort.in","r",stdin);
    freopen("Tahort.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
}

void work()
{
    int head=1,tail=0,maxnow=0;
    while(tail<n)
    {
        tail++;//尾指针+1
        if(maxnow<a[tail]) maxnow=a[tail];//更新当前最大值
        else{
            int k=tail;
            while(k<n && a[k]<=maxnow)
            {
                if(a[k]<=a[head]) {k=0;break;}
                k++;
            }
            if(a[k]>maxnow) {tail=k;maxnow=a[k];}
            else {head=tail;maxnow=a[head];}
        }
        if(head<tail) ans=max(ans,tail-head+1);
        if(n-head+1<=ans) break;
    }

    printf("%d",ans);
}

int main()
{
    init();
    work();
    return 0;
}

  

 

 

 

这一题的标准算法是RMQ,现在正在尽力写,后面争取放上代码........

 

 

未完待续.....

 

 

posted @ 2012-11-05 13:47  jiangzh  阅读(618)  评论(0编辑  收藏  举报