st表

 

ST表

ST表的功能很简单

它是解决RMQ问题(区间最值问题)的一种强有力的工具

它可以做到O(nlogn)预处理,O(1)查询最值

算法学习

  • ST表是利用的是倍增的思想

   我们用 f[i][j]  表示,从 位置开始的 2^j 个数中的最大值(同样可以最小值,也可是别的),例如 f[i][1] 表示的是 i 位置和 i+1 位置中两个数的最大值

           那么转移的时候我们可以把当前区间拆成两个区间并分别取最大值(注意这里的编号是从1开始的)

  • 如何实现?

 

    

   首先预处理出我的log数组和d数组(位运算更快,看不懂<<和>>百度吧)

     log[n]表示log2(n)向下取整,即使得2^log[i]最大且不超过i   

     d[i]表示2^i(你接下来d[i]的位置总打1<<i也行吧..)

1 log[0]=-1;d[0]=1;
2 for(R int i=1;i<=n;i++)f[i][0]=ri(),log[i]=log[i>>1]+1;
3 for(R int i=1;i<=19;i++)d[i]=d[i-1]*2;

   其次可以预处理出,f[i][0]等于这个数字本身。

   两个for:

1 for(int j=1;j<=log[n];j++)
2     for (int i=1;i+d[j]-1<=n;i++)
3         f[i][j]=max(f[i][j-1],f[i+d[j-1]][j-1]);

 

          转移方程如上。

     什么意思??

     对于每个区间(长度大于1)都可以对半分。这个区间的max从两个区间的最大值中取出。

   所以,我们先预处理好每个2^i,2^j次方区间的最大值,上图蓝色线表示f[i][j],可以轻松得到方程 f[i][j] = max( f[i][j-1], f[i+2^(j-1)] [j-1] );

查询

       

     假设我们查询区间(l,r)

   那么我们算出区间长度len=r-l+1,求出 k=log[len],那么显然2^k<=len

      如图,我们求出红色线段和绿色线段最大值中的最大值即可

   如下代码,我直接 len=log[r-l+1],当成k看也一样

max(f[l][len],f[r-d[len]+1][len])

   当然,以上只是st表常用的应用之一。

   练习题稍后补充。

1.luoguP3865 【模板】ST表

 1 #include <iostream>
 2 #include<cstdio> 
 3 #define R register
 4 using namespace std;
 5 const int N=100000;
 6 int n,m;
 7 int f[N+5][20],log[N+5],d[20];
 8 inline int ri(){
 9     char c=getchar();int x=0,w=1;
10     while(!isdigit(c)){if(c=='-')w=-1;c=getchar();}
11     while( isdigit(c)){x=(x<<3)+(x<<1)+c-48;c=getchar();}
12     return x*w;
13 }
14 int main(){
15     int l,r,len;
16     n=ri();m=ri();
17     log[0]=-1;d[0]=1;//就这么预处理吧。log和d数组前文有交代
18     for(R int i=1;i<=n;i++)f[i][0]=ri(),log[i]=log[i>>1]+1;
19     for(R int i=1;i<=19;i++)d[i]=d[i-1]*2;
20     for(int j=1;j<=log[n];j++)//保证不越界
21         for (int i=1;i+d[j]-1<=n;i++)
22             f[i][j]=max(f[i][j-1],f[i+d[j-1]][j-1]);//预处理
23     while(m--) {//询问
24         l=ri();r=ri();
25         len=log[r-l+1];
26         printf("%d\n",max(f[l][len],f[r-d[len]+1][len]));
27     }
28     return 0;
29 }

 

  

posted @ 2018-12-26 19:59  flickerr  阅读(225)  评论(0)    收藏  举报