POJ 2452 Sticks Problem [RMQ+二分]

19 篇文章 0 订阅
2 篇文章 0 订阅


/*
题意:给你一组数a[n],求满足a[i] < a[k] < a[j] (i <= k <= j)的最大的j-i。

解法:RMQ + 二分。
枚举i,利用二分求出a[i]右边第一个小于a[i]的数的位置k,
再求出[i, k]中最大值的位置j,若a[j] > a[i],则更新结果。
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>

using namespace std;

const int maxn = 50010;
int n, len[maxn];
// 分别存储的是最大值和最小值的下标 
int minl[maxn][20], maxl[maxn][20];


int _min(int l, int r)
{
    if (len[l] < len[r]) return l;
    return r;
}

int _max(int l, int r)
{
    if (len[l] > len[r]) return l;
    return r;
}

void init()
{
    for (int i = 1; i <= n; ++i)
        minl[i][0] = maxl[i][0] = i;
    for (int j = 1; (1<<j) <= n; ++j)
    {
        for (int i = 1; i + (1<<j) - 1 <= n; ++i)
        {
            minl[i][j] = _min(minl[i][j-1], minl[i+(1<<(j-1))][j-1]);
            maxl[i][j] = _max(maxl[i][j-1], maxl[i+(1<<(j-1))][j-1]);
        }
    }
}

int minrmq(int l, int r)
{
    int k = (int)(log(double(r) - l + 1) / log(2.0));
    return _min(minl[l][k], minl[r+1-(1<<k)][k]);
}

int maxrmq(int l, int r)
{
    int k = (int)(log(double(r) - l + 1) / log(2.0));
    return _max(maxl[l][k], maxl[r+1-(1<<k)][k]);
}

int bsearch(int x, int l, int r)
{
    while (l <= r)
    {
        if (l == r) return l;
        int m = (l + r) >> 1;
        if (len[x] < len[minrmq(l, m)])
            l = m + 1;
        else r = m;
    }
}

void work()
{
    int ans = 0;
    for (int i = 1; i + ans < n; ++i)
    {
        int r = bsearch(i, i + 1, n);
        int k = maxrmq(i, r);
        if(len[k] > len[i])
            ans = max(ans, k - i);
    }
    if (ans == 0) printf("-1\n");
    else printf("%d\n", ans);
}

int main()
{
    while (scanf("%d", &n) != EOF)
    {
        for (int i = 1; i <= n; ++i)
            scanf("%d", &len[i]);
        init();
        work();
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值