POJ2019:二维ST算法解决静态方阵最值问题

Posted aininot260

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ2019:二维ST算法解决静态方阵最值问题相关的知识,希望对你有一定的参考价值。

我们其实是很有必要把ST算法拓展到二维的,因为二维的RMQ问题还是不少的

int N,B,K;
int mm[505];
int val[maxn][maxn];
int dpmin[maxn][maxn][8][8];
int dpmax[maxn][maxn][8][8];

这里的N是方阵的长宽,此处是正方形题目,然后mm是预处理出来的,方便计算指数

dpmin和dpmax就是预处理数组了

然后看一下开局预处理:

void initRMQ(int n,int m)
{
    for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
        dpmin[i][j][0][0]=dpmax[i][j][0][0]=val[i][j];
    for(int ii=0;ii<=mm[n];ii++)
    for(int jj=0;jj<=mm[m];jj++)
    if(ii+jj)
    for(int i=1;i+(1<<ii)-1<=n;i++)
    for(int j=1;j+(1<<jj)-1<=m;j++)
    {
        if(ii)
        {
            dpmin[i][j][ii][jj] = min(dpmin[i][j][ii-1][jj],dpmin[i+(1<<(ii-1))][j][ii-1][jj]);
            dpmax[i][j][ii][jj] = max(dpmax[i][j][ii-1][jj],dpmax[i+(1<<(ii-1))][j][ii-1][jj]);
        }
        else
        {
            dpmin[i][j][ii][jj] = min(dpmin[i][j][ii][jj-1],dpmin[i][j+(1<<(jj-1))][ii][jj-1]);
            dpmax[i][j][ii][jj] = max(dpmax[i][j][ii][jj-1],dpmax[i][j+(1<<(jj-1))][ii][jj-1]);
        }
    }
}

我们看预处理的时候还是比较明朗的,当然别忘了在主函数把mm初始化好

    mm[0]=-1;
    for(int i=1;i<=500;i++)
        mm[i]=((i&(i-1))==0)?mm[i-1]+1:mm[i-1];

然后就是求最大值和最小值的函数了,这里,一定要仔细地去写,很容易写错:

int rmq1(int x1,int y1,int x2,int y2)  //max
{
    int k1=mm[x2-x1+1];
    int k2=mm[y2-y1+1];
    x2=x2-(1<<k1)+1;
    y2=y2-(1<<k2)+1;
    return max(max(dpmax[x1][y1][k1][k2],dpmax[x1][y2][k1][k2]),max(dpmax[x2][y1][k1][k2],dpmax[x2][y2][k1][k2]));
}
int rmq2(int x1,int y1,int x2,int y2)
{
    int k1=mm[x2-x1+1];
    int k2=mm[y2-y1+1];
    x2=x2-(1<<k1)+1;
    y2=y2-(1<<k2)+1;
    return min(min(dpmin[x1][y1][k1][k2],dpmin[x1][y2][k1][k2]),min(dpmin[x2][y1][k1][k2],dpmin[x2][y2][k1][k2]));
}

这个式子确实很长的

最后给出题目完整的实现:

 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 const int maxn=255;
 5 int N,B,K;
 6 int mm[505];
 7 int val[maxn][maxn];
 8 int dpmin[maxn][maxn][8][8];
 9 int dpmax[maxn][maxn][8][8];
10 void initRMQ(int n,int m)
11 {
12     for(int i=1;i<=n;i++)
13     for(int j=1;j<=m;j++)
14         dpmin[i][j][0][0]=dpmax[i][j][0][0]=val[i][j];
15     for(int ii=0;ii<=mm[n];ii++)
16     for(int jj=0;jj<=mm[m];jj++)
17     if(ii+jj)
18     for(int i=1;i+(1<<ii)-1<=n;i++)
19     for(int j=1;j+(1<<jj)-1<=m;j++)
20     {
21         if(ii)
22         {
23             dpmin[i][j][ii][jj] = min(dpmin[i][j][ii-1][jj],dpmin[i+(1<<(ii-1))][j][ii-1][jj]);
24             dpmax[i][j][ii][jj] = max(dpmax[i][j][ii-1][jj],dpmax[i+(1<<(ii-1))][j][ii-1][jj]);
25         }
26         else
27         {
28             dpmin[i][j][ii][jj] = min(dpmin[i][j][ii][jj-1],dpmin[i][j+(1<<(jj-1))][ii][jj-1]);
29             dpmax[i][j][ii][jj] = max(dpmax[i][j][ii][jj-1],dpmax[i][j+(1<<(jj-1))][ii][jj-1]);
30         }
31     }
32 }
33 int rmq1(int x1,int y1,int x2,int y2)  //max
34 {
35     int k1=mm[x2-x1+1];
36     int k2=mm[y2-y1+1];
37     x2=x2-(1<<k1)+1;
38     y2=y2-(1<<k2)+1;
39     return max(max(dpmax[x1][y1][k1][k2],dpmax[x1][y2][k1][k2]),max(dpmax[x2][y1][k1][k2],dpmax[x2][y2][k1][k2]));
40 }
41 int rmq2(int x1,int y1,int x2,int y2)
42 {
43     int k1=mm[x2-x1+1];
44     int k2=mm[y2-y1+1];
45     x2=x2-(1<<k1)+1;
46     y2=y2-(1<<k2)+1;
47     return min(min(dpmin[x1][y1][k1][k2],dpmin[x1][y2][k1][k2]),min(dpmin[x2][y1][k1][k2],dpmin[x2][y2][k1][k2]));
48 }
49 int main()
50 {
51     mm[0]=-1;
52     for(int i=1;i<=500;i++)
53         mm[i]=((i&(i-1))==0)?mm[i-1]+1:mm[i-1];
54     while(scanf("%d%d%d",&N,&B,&K)==3)
55     {
56         for(int i=1;i<=N;i++)
57         for(int j=1;j<=N;j++)
58             scanf("%d",&val[i][j]);
59         initRMQ(N,N);
60         int x,y;
61         while(K--)
62         {
63             scanf("%d%d",&x,&y);
64             printf("%d
",rmq1(x,y,x+B-1,y+B-1)-rmq2(x,y,x+B-1,y+B-1));
65         }
66     }
67     return 0;
68 }

以上是关于POJ2019:二维ST算法解决静态方阵最值问题的主要内容,如果未能解决你的问题,请参考以下文章

ST算法(区间最值)

POJ 2019 Cornfields 二维线段树的初始化与最值查询

POJ2019 Cornfields 二维ST表

ST算法

二维 ST POJ 2019

ST表的原理及其实现