POJ2452 Sticks Problem

1 篇文章 0 订阅
1 篇文章 0 订阅

POJ2452 Sticks Problem

Time Limit: 6000MS  MemoryLimit: 65536K

TotalSubmissions: 9607  Accepted: 2546

Description

Xuanxuan has n sticks of different length.One day, she puts all her sticks in a line, represented by S1, S2, S3, ...Sn.After measuring the length of each stick Sk (1 <= k <= n), she finds thatfor some sticks Si and Sj (1<= i < j <= n), each stick placed betweenSi and Sj is longer than Si but shorter than Sj. 

Now given the length of S1, S2, S3, …Sn, you are required to find the maximumvalue j - i.

Input

The input contains multiple test cases. Eachcase contains two lines. 
Line 1: a single integer n (n <= 50000), indicating the number ofsticks. 
Line 2: n different positive integers (not larger than 100000), indicating thelength of each stick in order.

Output

Output the maximum value j - i in a singleline. If there is no such i and j, just output -1.

Sample Input

4

5 4 3 6

4

6 5 4 3

Sample Output

1

-1

Source

POJ Monthly,static


题意概述:

给定长度为n的序列s1…sn,求子序列si…sj使得子序列中最小值为si,最大值为sj。

 

解法一:

                                                                

算法:RMQ(预处理)+枚举+二分(不加赘述 >_< )

时间复杂度:

1.      RMQ预处理:O(NlogN)

2.      枚举+二分:O(NlogN)

 

解法二:*/

算法:RMQ(预处理)+单调栈

        单调栈的基本操作:

        维护栈使得栈中的元素具有单调性,即单调递增或递减。当即将入栈的元素不满足栈的单调性的时候,弹出栈顶元素知道新加入的元素仍然满足栈中元素的单调性。

 

解题步骤:

1.      首先RMQ预处理出每段区间的最大值及取最大值元素的位置

2.      按1到n的顺序将原序列中的元素依次加入到栈中,维护栈使得栈中元素单调递增

3.      当栈中某一元素被弹出时

记被弹出元素序号为i,当前即将加入的元素序号为j,根据栈的单调性可知sj为第一个比si小的元素,即si+1..sj-1都大于si。因此若子序列以si开头,则最大可能的右端点为sj-1

4.      用RMQ求区间[i+1..j-1]的最大值序号k,则以i开头的子序列最大长度为(k-i)

5.      持续更新子序列长度的最大值

 

应用此方法时应注意:

1.      为防止栈中元素都被弹出导致访问越界,应设定栈底元素值为-1(或更小的数)以保证其永远不会被弹出

2.      为防止栈中最后遗留一部分单调递增的元素,设原序列第n+1个元素(即sn+1)=0(但不要比栈底元素小)以保证原序列中每个元素都能被弹出

 

时间复杂度分析:

1.        RMQ预处理:O(NlogN)

2.        单调栈:由于每个元素入栈一次退栈一次,退栈时查询区间最大值(即RMQ问题的询问)时间复杂度为O(1),所以单调栈总时间复杂度为O(N)

这种做法会比解法一快一点,而且代码好写一点哦~
附:代码(RMQ+单调栈)/*代码写的比较挫勿喷。。。*/

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<math.h>
usingnamespace std;
constint maxn=50000;
structnode
{
    int xx,pp;
}rmq[maxn+100][50],stack[maxn+100],tmp;
nodemax(node x,node y)
{
    if (x.xx>y.xx) return x;
    else return y;
}
intn,tot,ans,a[maxn+10],tail,key,i,j;
intmain()
{
   /*freopen("poj2452.in","r",stdin);
   freopen("poj2452.out","w",stdout);*/
    while (scanf("%d",&n)!=EOF){
        ans=-1;
        for (i=1;i<=n;i++)
            scanf("%d",&a[i]);
        n++; a[n]=-1;
        while ((1<<tot-1)<=n) tot++;
        for (i=1;i<=n;i++){
            rmq[i][0].xx=a[i];
            rmq[i][0].pp=i;
        }
        for (i=1;i<=tot;i++)
            for(j=1;j+(1<<i)-1<=n;j++)
               rmq[j][i]=max(rmq[j][i-1],rmq[j+(1<<i-1)][i-1]);
        /*for (i=1;i<=n;i++){
            for (j=0;j<=tot;j++)
                printf("%d",rmq[i][j].xx);
            printf("\n");
        }*/
        stack[0].xx=-10; tail=0;
        for (i=1;i<=n;i++){
            if (i==n){
                i=n;
            }
            while (stack[tail].xx>a[i]){
                key=stack[tail].pp;
                tot=1;
                while((1<<tot)<=i-1-key) tot++;
                tot--;
               tmp=max(rmq[key][tot],rmq[i-(1<<tot)][tot]);
                ans=max(ans,abs(tmp.pp-key));
                tail--;
            }
            tail++;
            stack[tail].xx=a[i];
            stack[tail].pp=i;
        }
        if (ans>0)printf("%d\n",ans);
        else printf("-1\n");
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值