poj2452

题意:给出n个互不相同的数字,要求一个最大的子段,使得该子段内所有数(除了两端以外),值都在两端的数字之间,且不能等于两端的数。

分析:先对整个数组分别构造最大值RMQ和最小值RMQ的st数组。然后,枚举子段起点,对于每个起点求出这个起点是区间最小值的最远终点(用二分查找)。然后在这个区间内找到最大值位置,从起点到最大值位置这个区间就是起点所对应的符合题意的最大区间。枚举过所有的起点之后,结果就求出来了。

View Code
#include <iostream>

#include <cstdio>

#include <cstdlib>

#include <cstring>

#include <cmath>

using namespace std;



#define inf 0x3f3f3f3f

#define maxn 50005



int n;

int f[maxn];

int st1[maxn][32];

int st2[maxn][32];

int d[32];



void InitRMQ1(int f[], int n, int st[][32])

{

    int i, j;

    for (d[0] = 1, i = 1; i < 21; i++)

        d[i] = 2 * d[i - 1];

    for (i = 0; i < n; i++)

        st[i][0] = i;

    int k = int(log(double(n))/log(2)) + 1;

    for (j = 1; j < k; j++)

        for (i = 0; i < n; i++)

            if (i + d[j - 1] - 1 < n)

            {

                if (f[st[i][j - 1]] < f[st[i + d[j - 1]][j - 1]])

                    st[i][j] = st[i + d[j - 1]][j - 1];

                else

                    st[i][j] = st[i][j - 1];

            }

            else

                break;

}



int query1(int x, int y, int st[][32])

{

    int k = int(log(double(y - x + 1)) / log(2.0));

    if (f[st[x][k]] < f[st[y - d[k] + 1][k]])

        return st[y - d[k] + 1][k];

    return st[x][k];

}



void InitRMQ2(int f[], int n, int st[][32])

{

    int i, j;

    for (d[0] = 1, i = 1; i < 21; i++)

        d[i] = 2 * d[i - 1];

    for (i = 0; i < n; i++)

        st[i][0] = i;

    int k = int(log(double(n))/log(2)) + 1;

    for (j = 1; j < k; j++)

        for (i = 0; i < n; i++)

            if (i + d[j - 1] - 1 < n)

            {

                if (f[st[i][j - 1]] > f[st[i + d[j - 1]][j - 1]])

                    st[i][j] = st[i + d[j - 1]][j - 1];

                else

                    st[i][j] = st[i][j - 1];

            }

            else

                break;

}



int query2(int x, int y, int st[][32])

{

    int k = int(log(double(y - x + 1)) / log(2.0));

    if (f[st[x][k]] > f[st[y - d[k] + 1][k]])

        return st[y - d[k] + 1][k];

    return st[x][k];

}



void input()

{

    for (int i = 0; i < n; i++)

        scanf("%d", &f[i]);

}





int binary_search(int a)

{

    int l = a, r = n - 1;

    while (l < r)

    {

        int mid = (l + r) / 2 + ((l + r) & 1);

        if (query2(a, mid, st2) == a)

            l = mid;

        else

            r = mid - 1;

    }

    return l;

}



int work()

{

    int ret = 0;

    for (int i = 0; i < n; i++)

    {

        int r = query1(i, binary_search(i), st1);

        ret = max(ret, r - i);

    }

    if (ret == 0)

        return -1;

    return ret;

}



int main()

{

    //freopen("t.txt", "r", stdin);

    while (~scanf("%d", &n))

    {

        input();

        InitRMQ1(f, n, st1);

        InitRMQ2(f, n, st2);

        printf("%d\n", work());

    }

    return 0;

}

你可能感兴趣的:(poj)