ST表

luogu3865

这就是倍增的思想、、

不支持更改,建表是nlogn

然后查询两个部分重叠比较,O(1)

#include<cstdio>
#include<cmath>
int n,m;
int a[100103],st[101000][32];

void read(int &n){
    int f=1;n=0;char s=getchar();
    while('9'<s||s<'0'){if(s=='-')f=-1;s=getchar();}
    while('0'<=s&&s<='9'){n=n*10+s-'0';s=getchar();}
    n*=f;
}

int max(int x,int y){
    return x>y?x:y;
}

void rmq_st(){
    for(int i = 1;i <= n;++ i)
         st[i][0]=a[i];//初始化,它本身的前缀
     for(int j=1;(1<<j)<=n;++j){//这个是2^j 
         for(int i=1;i+(1<<j)-1<=n;++i){//1~n
             st[i][j]=max(st[i][j-1],st[i+(1<<(j-1))][j-1]); 
        }
     }
}

int sum(int l, int r){
    int k=(log2(r-l+1));//求log 
    return max(st[l][k],st[r-(1<<k)+1][k]);//区间最大值在
    //他右边或者左边,2^k是恰好小鱼他们之间距离的长度
    //所以最大值一定包含里面,重合部分不受影响,又不是求sum 
}      

int main()
{
    read(n);read(m);
    for(int i = 1;i <= n;++ i){
        read(a[i]);//用a数组建一个st表
    }
    rmq_st();
    int l_, r_; 
    while(m--){
        read(l_);read(r_);
        printf("%d\n",sum(l_,r_));
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/lovedsr/p/8989857.html