• luogu P3865 【模板】ST表


    luogu P3865 【模板】ST表

    利用递推解决区间最值问题

    建成后,不支持修改区间上某一点的值

    建表O(nlogn),查询O(1)

    1<< t == 二的 t 次方

    p[ k ][ i ]==从 i 开始包括 i 长为 2^k 的区间的最值

    p[ 0 ][ i ]即为 a[ i ]的值本身

    1.建表时

        区间[ i , i + 2^k -1 ] 最值等于区间[ i , i +2( k-1 )-1 ]与区间 [ i +2( k -1) ][ i + 2^k -1]的最值

    p[k][i]=max(p[k-1][i],p[k-1][i+(1<<(k-1))])

        最开始知道所有的 p[ 0 ][ i ],用 p[ 0 ][ i ]去推 p[ 1 ][ i ]直到到 p[ t ][ i ]

    2.询问时

        区间[ l ,r ]最值等于区间[ l , l +2^k -1]与区间[ r -2^k +1 , r ]的最值

        由于k 取log2( r - l +1)向下取整,p[ k ][ l ]与p[ t ][ r – (1 << t) + 1]取最值返回

        2^(k+1)一定能包含整个区间[ l ,r ],所以这两个 P 数组所代表的区间,一定会覆盖所求区间,且不会越界

    #include<cstdio>
    #include<cmath>      //log2()函数需调用<cmath>
    #include<iostream>   //max,min,swap调用<iostream>
    using namespace std;
    int n,m;
    int p[50][100001],a[100001];
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        for(int i=1;i<=n;i++) p[0][i]=a[i];
        int t=log2(n);
        for(int k=1;k<=t;k++)   //建表
            for(int i=1;i+(1<<k)-1<=n;i++)
                p[k][i]=max(p[k-1][i],p[k-1][i+(1<<(k-1))]);int l,r;
        for(int i=1;i<=m;i++)   //询问
        {
            scanf("%d%d",&l,&r);
            t=log2(r-l+1);
            printf("%d
    ",max(p[t][l],p[t][r-(1<<t)+1]));
        }
        return 0;
    }
  • 相关阅读:
    [洛谷P2523] HAOI2011 Problem c
    [CF156D] Clues
    [洛谷P4769] NOI2018 冒泡排序
    [CF605E] Intergalaxy Trips
    [洛谷P4492] HAOI2018 苹果树
    [洛谷P3349] ZJOI2016 小星星
    [洛谷P4336] SHOI2016 黑暗前的幻想乡
    [洛谷P5364] SNOI2017 礼物
    [洛谷P2606] ZJOI2010 排列计数
    [洛谷P6078] CEOI2004 candy
  • 原文地址:https://www.cnblogs.com/QAQq/p/10301856.html
Copyright © 2020-2023  润新知