ST deepen the understanding of the algorithm (Sparse Table)

Copyright: private individuals do question summed up ~ https://blog.csdn.net/tb_youth/article/details/89684945

Sparse Table (sparse table): referred ST
ST algorithm is based on dynamic programming algorithm, so it is essentially dynamic programming.
Its time complexity is: O (nlogn) -O (q ).
It is no longer appropriate interval for the data to make changes in the value of most inquiries.
Assuming now that there is a set of data, the minimum requirement [l, r] in the.
First, we know that:
for the interval [l, r]: its interval lengthlen = r-l+1 ;
below the basic idea of ST:
it is based on dynamic programming, the best condition is: dp[i][j]
dp[i][j]indicates the length of interval from start i ^ 2 j one section (i.e., the [i,(2^j)-1]) the most value

(r - l + 1 = 2^j, l = i,  ---->  r = i+(2^j)+1)

For the interval [l, r], it can be divided into two sections, i.e., two uniform interval is divided into two:
[L, R & lt] ----> [L, R & lt '] + [L', R & lt], Therefore, the interval lengths of the two sections is len / 2,
if dp [i] [j] represents [l, r] the minimum of the interval,
then for dp[i][j] = min(dp[i][j-1],dp[i+2^(j-1)][j-1]), that is the state transition equation .
It is understood that:
the interval length is halved: (2^j)/2 = 2^(j-1), the second two-dimensional sub-sections. 1 to J
DP [I ^ 2 + (. 1-J)] [-J. 1]):

r - l' + 1 = 2^(j-1),r = i + 2^j -1  ----> 
 l' = i+2^j -1+1-2^(j-1)   -------> l' = i + 2^(j-1)

boundary:

dp[i][0] = a[i]  (i = 1...n)

Write code:

for(int i = 1; i <= n; i++)
  {
      cin>>dp[i][0];
  }
  for(int j = 1; 1<<j <= n; j++)
  {
      for(int i = 1; i+(1<<j)-1<=n; i++)
      {
          dp[i][j] = min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
      }
  }

For i, an interval [l, r],

dp[i][j],l = i,r-i +1 =  2^j----->  r = i + (1<<j)-1,r <= n,
所以:i+(1<<j)-1 <= n

Interval Query:
[l, r] query minimum,
so as to satisfy k 2 ^k <= r-l+1is the largest integer ,
then for the interval [l, r] is in the interval beginning and a length l 2 ^ k, and r and ending interval length of 2 ^ k
two cover sections

k = log2(r-l+1)

Then
ans = min(dp[l][1<<k],dp[r-(1<<k)+1][k])
l 'r is represented by:

 r - l' + 1 = 1 << k    --->  l' = r - (1<<k) + 1

Interval query code can be written as:

int rmq(int L, int R)
     {
       //int k = 0;
       //while(1<<(k+1) <= R-L+1) k++;
       int k = log2(r-l+1);
       return  min(dp[l][1<<k],dp[r-(1<<k)+1][k]);
     }

Title:
https://www.luogu.org/problemnew/show/P1816
Code:
(pre-k)

#include <iostream>
#define MAXM 100005
#define N 30
#define LL long long
using namespace std;
LL dp[MAXM][N];
LL lg[MAXM];//k = lg[r-l+1]
int main()
{
  int m,n;
  cin>>m>>n;
  lg[0] = -1;
  for(int i = 1; i <= m; i++)
  {
      cin>>dp[i][0];
      lg[i] = lg[i>>1] + 1;
  }
  for(int j = 1; 1<<j <= m; j++)
  {
      for(int i = 1; i+(1<<j)-1<=m; i++)
      {
          dp[i][j] = min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
      }
  }
  int flag = 1;
  while(n--)
  {
      int l,r;
      cin>>l>>r;
      int k = lg[r-l+1];
      if(flag) 
      {
          cout<<min(dp[l][k],dp[r-(1<<k)+1][k]);
          flag = 0;
      }
      else
      cout<<" "<<min(dp[l][k],dp[r-(1<<k)+1][k]);
  }
  cout<<endl;
  return 0;
}

Guess you like

Origin blog.csdn.net/tb_youth/article/details/89684945