POJ 2452 Sticks Problem (RMQ + 预处理)

大体题意:

给你n 个数,要求选择一个区间l,r 使得 l~r 之间的数a[i]  满足  a[l] < a[i] < a[r] 求最大的r-l?

思路:

rmq+预处理!

我们可以枚举区间的左端点l,我们需要找到左端点l 的右方第一个小于等于a[l]的位置k,然后我们求出 l ~ k-1区间内的最大值a[pos],如果最大值大于a[l],那么 pos - l 就是答案之一,更新一下最大值即可!

那么问题来了:

rmq求的是 区间内的最大值,但是我们这个题目不仅要求出最大值,还要求出最大值所在的位置!

其实也很好解决,稍微改动一下rmq 即可!  我们让rmq 中的dp[i][j] 记录的是  第i 个位置开始 长度为(1<<j) 的最大值所在位置,这样两个问题就都解决了,注意 如果rmq中两个区间 左边的最大值和右边的最大值相等的话要记录左端点的最大值,否则右边最大值会和左边最大值冲突,解不合法!

然后就是如何求出每一个位置  的右方第一个小于等于他的位置?

我们开一个数组预处理,令r[i]为第i 个位置右方第一个小于等于a[i]的位置!  为了方便,我们可以在原始数据的末尾在加一个-inf  无限小!

那么如果a[i] >= a[i+1]直接r[i] = i + 1;

否则就让他一直往后跳,跳到头为止!

详细见代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = 50000 + 7;
const int inf = 0x3f3f3f3f;
int a[maxn];
int dp[maxn][20], n, r[maxn];
void rmq(){
    for (int i = 0; i < n; ++i) dp[i][0] = i;
    for (int j = 1; (1 << j) <= n; ++j){
        for (int i = 0; i + (1 << j) - 1 < n; ++i){
            int t1 = dp[i][j-1];
            int t2 = dp[i+(1<<(j-1))][j-1];
            if (a[t1] >= a[t2]) dp[i][j] = t1;
            else dp[i][j] = t2;
        }
    }
}
int query(int l,int r){
    int k = 0;
    while((1 << (k+1) ) <= r-l + 1)++k;
    int t1 = dp[l][k];
    int t2 = dp[r-(1<<k)+1][k];
    if (a[t1] >= a[t2]) return t1;
    return t2;
}
int main(){
    while(scanf("%d",&n) == 1){
        for (int i = 0; i < n; ++i){
            scanf("%d",&a[i]);
        }
        rmq();
        a[n] = -inf;
        r[n-1] = n;
        for (int i = n-2; ~i; --i){
            if (a[i] >= a[i+1]) r[i] = i+1;
            else{
                int cur = i+1;
                while(1){
                    if (a[cur] <= a[i]){
                        r[i] = cur;
                        break;
                    }
                    cur = r[cur];
                }
            }
        }
        int ans = 0;
        for (int i = 0; i < n; ++i){
            int id = query(i,r[i]-1);
            if (a[id] > a[i]) ans = max(ans,id-i);
        }
        if (!ans)printf("-1\n");
        else printf("%d\n",ans);
    }


    return 0;
}




Sticks Problem
Time Limit: 6000MS Memory Limit: 65536K
Total Submissions: 10430 Accepted: 2771

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 that for some sticks Si and Sj (1<= i < j <= n), each stick placed between Si 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 maximum value j - i.

Input

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

Output

Output the maximum value j - i in a single line. 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

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值