ST表

直接上代码板子(要最大值直接改成max就好)

int d[1000006][25];
int mn[1000006];
void rmq_init()
{
    for(int i=1;i<=n;i++)
        d[i][0]=a[i];//初始化
    for(int j=1;(1<<j)<=n;j++)
      for(int i=1;i+(1<<j)-1<=n;i++)
        d[i][j]=min(d[i][j-1],d[i+(1<<(j-1))][j-1]);
    for(int len=1;len<=n;++len){
        int k=0;
        while((1<<(k+1))<=len)
            k++;
        mn[len]=k;
    }
}
int rmq(int L,int R)
{
    int k=mn[R-L+1];
    return min(d[L][k],d[R-(1<<k)+1][k]);
}

d[i][j]的值表示为区间(i,i+2^j-1)的最值

d[i][j]=min(d[i][j-1],d[i+(1<<(j-1))][j-1]);看起来很复杂 可以代入一个数据看看 让i=5,j=3

d[5][3]=min(d[5][2],d[9][2])

即min(5,12)=min((5,8),(9,12)); 这种推理便是动态规划的思想

如果假设我们要知道(5,10)区间的最值 首先我们求区间长度=6 , 而4是最大的小于6的2的幂次方 5+4-1=8 10-4+1=7

即min(5,10)=min((5,8),(7,10))

mn[]数组即为求最大的小于区间长度的2的幂次方 也可以用log2(r-l+1)来解决

(其实说那么多 记住代码模板就好哈哈哈哈哈)

例题洛谷P3865 //不用快读会TLE

#include <iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#include<cstring>
using namespace std;
int n,m;
int a[1000006];
int d[1000006][25];
int mn[1000006];
int L,R;
inline int read(){
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*f;
}
void rmq_init()
{
    for(int i=1;i<=n;i++)
        d[i][0]=a[i];
    for(int j=1;(1<<j)<=n;j++)
      for(int i=1;i+(1<<j)-1<=n;i++)
        d[i][j]=max(d[i][j-1],d[i+(1<<(j-1))][j-1]);
    for(int len=1;len<=n;++len){
        int k=0;
        while((1<<(k+1))<=len)
            k++;
        mn[len]=k;
    }
}
int rmq(int L,int R)
{
    int k=mn[R-L+1];
    return max(d[L][k],d[R-(1<<k)+1][k]);
}
int main(){
	cin >> n >> m;
	for(int i=1;i<=n;i++){
		a[i]=read();
	}
	rmq_init();
	for(int i=1;i<=m;i++){
		L=read();
		R=read();
		printf("%d\n",rmq(L,R));
	}
  return 0;
}




//  freopen("testdata.in", "r", stdin);
posted @ 2020-08-18 14:49  一个经常掉线的人  阅读(98)  评论(0)    收藏  举报