1. 程式人生 > >POJ2019:二維ST算法解決靜態方陣最值問題

POJ2019:二維ST算法解決靜態方陣最值問題

指數 rmq 方便 解決 最大值和最小值 st算法 完整 lse 正方

我們其實是很有必要把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\n",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算法解決靜態方陣最值問題