The excellent data structure with the most value in the interval---ST table

ST table, it sounds tall, in fact, there are many restrictions, only the most value problem can be calculated;

Why? Let's start with the principle;

The st table uses the idea of ​​multiplication: st[i][j] = min(st[i][j - 1],st[i + 2^(j - 1))][j - 1 ]);

The meaning is: the maximum value of 2^j consecutive positions from i is the maximum value of 2^(j-1) consecutive positions from i and i+2^(j-1) consecutive backwards The maximum value of 2^(j-1) positions;

Well, the structure is established, so how to query?

A formula: 2^log(a)>a/2  .

So, when querying (x,y), we set k=log(y-x+1);

ans=max(f[x][k],f[y-(1<<k)+1][k]);

Now we know that the reason why the ST table can only find the maximum value is that when it is queried, in order to save time complexity, the query interval takes the union operation; in this way, the correct answer cannot be obtained by calculating the interval sum;

Attachment: 1. Find the one-dimensional ST maximum value:

 

#include <bits/stdc++.h>
#define int long long
using namespace std;
int a[100010];
int f[100010][40],g[100010][40];
int n,q;
void build()
{
	for(register int i=1;i<=n;i++){
		f[i][0]=a[i];
		g[i][0]=a[i];
	}
	for(register int j=1;(1<<j)<=n;j++){
		for(register int i=1;(i+(1<<j)-1)<=n;i++){
			f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
			g[i][j]=min(g[i][j-1],g[i+(1<<(j-1))][j-1]);
		}
	}
}
int query(int x,int y)
{
	int tmp=log2(y-x+1);
	return max(f[x][tmp],f[y-(1<<tmp)+1][tmp])-min(g[x][tmp],g[y-(1<<tmp)+1][tmp]);
}
signed main()
{
	scanf("%lld%lld",&n,&q);
	for(register int i=1;i<=n;i++) scanf("%lld",&a[i]);
	build();
	for(register int i=1;i<=q;i++){
		int x,y;
		scanf("%lld%lld",&x,&y);
		printf("%lld\n",query(x,y));
	}
} 

 

 

The principle of the two-dimensional st table is to divide a square into 4 parts:

Let st[i][j][k] denote the maximum value in a square with upper left corner i, j and side length k.
st[i][j][k]=Max(st[i][j][k-1],st[i+(1<<k-1)][j][k-1],st[i ][j+(1<<k-1)][k-1],st[i+(1<<k-1)][j+(1<<k-1)][k-1]);

Similar to the one-dimensional ST table when querying, the union operation is performed;

#include <bits/stdc++.h>
#define inc(i,a,b) for(register int i=a;i<=b;i++)
using namespace std;
int a,b,n;
int mmap[1001][1001];
int f[1001][1001][8],g[1010][1010][8];
void build()
{
	inc(i,1,a){
		inc(j,1,b){
			f[i][j][0]=mmap[i][j];
			g[i][j][0]=mmap[i][j];
		}
	}
	for(int k=1;k<=7;k++){
		for(int i=1;i+(1<<k)-1<=a;i++){
			for(int j=1;j+(1<<k)-1<=b;j++){
				f[i][j][k]=max(f[i+(1<<k-1)][j+(1<<k-1)][k-1],f[i+(1<<k-1)][j][k-1]);
				f[i][j][k]=max(f[i][j][k],f[i][j+(1<<k-1)][k-1]);
				f[i][j][k]=max(f[i][j][k],f[i][j][k-1]);
				g[i][j][k]=min(g[i+(1<<k-1)][j+(1<<k-1)][k-1],g[i+(1<<k-1)][j][k-1]);
				g[i][j][k]=min(g[i][j][k],g[i][j+(1<<k-1)][k-1]);
				g[i][j][k]=min(g[i][j][k],g[i][j][k-1]);
			}
		}
	}
}
int query(int x,int y,int goal)
{
	long long tmp1=max(f[x][y][goal],f[x+n-(1<<goal)][y][goal]);
	long long tmp2=max(f[x][y+n-(1<<goal)][goal],f[x+n-(1<<goal)][y+n-(1<<goal)][goal]);
	long long tmp3=max(tmp1,tmp2);
	long long tmp4=min(g[x][y][goal],g[x+n-(1<<goal)][y][goal]);
	long long tmp5=min(g[x][y+n-(1<<goal)][goal],g[x+n-(1<<goal)][y+n-(1<<goal)][goal]);
	long long tmp6=min(tmp4,tmp5);
	return tmp3-tmp6;
}
signed main()
{
	scanf("%d%d%d",&a,&b,&n);
	inc(i,1,a){
		inc(j,1,b){
			scanf("%d",&mmap[i][j]);
		}
	}
	build();
	int goal=log2(n);
	int ans=INT_MAX;
	inc(i,1,a-n+1){
		inc(j,1,b-n+1){
			ans=min(ans,query(i,j,goal));
		}
	}
	cout<<ans;
}
 

 When making one-dimensional and two-dimensional ST tables, we can introduce: three-dimensional ST tables, or even four-dimensional ST tables; but because of their high time complexity and large memory requirements, we no longer need them . But this kind of thinking can be applied elsewhere.

 

Reprinted in: https://www.cnblogs.com/kamimxr/p/11608543.html

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326525792&siteId=291194637