• 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;
    }
  • 相关阅读:
    XML基础总结
    异常处理
    集合总结
    事件源与监听器
    JAVA中的GUI---swing 和awt
    docker搭建wordpress
    Jenkins--第四关_扩展
    docker 安装centos 7
    Jenkins_第五关_系统管理(1)
    Jenkins--第三关_Gitlab安装和配置(续)
  • 原文地址:https://www.cnblogs.com/rainydays/p/2584576.html
Copyright © 2020-2023  润新知