`
java-mans
  • 浏览: 11415677 次
文章分类
社区版块
存档分类
最新评论

POJ 2019 二维RMQ

 
阅读更多

题意很简单 就不说了

为了把它推广成矩形的

写了这种查询是O(n)的方法

当然还有O(1)的矩形的方法了 只不过太麻烦了

但是对于正方形来讲 还是比较好弄的

#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <cstdio>
#include <cmath>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <stack>
#define eps 1e-5
#define MAXN 255
#define MAXM 111111
#define INF 1000000000
using namespace std;
int mx[MAXN][MAXN][8], mi[MAXN][MAXN][8];
int n, b, q, a, c;
void rmqinit()
{
    int l = int(log(double(n)) / log(2.0)) ;
    for(int k = 1; k <= n ; k++)
        for(int j = 1; j <= l; j++)
            for(int i = 1; i + (1 << (j - 1))- 1 <= n; i++)
            {
                mx[k][i][j] = max(mx[k][i][j - 1], mx[k][i + (1 << (j - 1 ))][j - 1]) ;
                mi[k][i][j] = min(mi[k][i][j - 1], mi[k][i + (1 << (j - 1 ))][j - 1]) ;
            }
}
int rmqmax(int lx, int ly, int rx, int ry) // lx, ly为左上角的点 rx ry为右下角的点
{
    int l = int(log(double(ry - ly + 1)) / log(2.0));
    int ret = -1;
    for(int k = lx; k <= rx ; k++)
        ret = max(ret, max(mx[k][ly][l], mx[k][ry - (1 << l) + 1][l]));
    return ret;
}
int rmqmin(int lx, int ly, int rx, int ry) // lx, ly为左上角的点 rx ry为右下角的点
{
    int l = int(log(double(ry - ly + 1)) / log(2.0));
    int ret = INF;
    for(int k = lx; k <= rx ; k++)
        ret = min(ret, min(mi[k][ly][l], mi[k][ry - (1 << l) + 1][l]));
    return ret;
}
int main()
{
    while(scanf("%d%d%d", &n, &b, &q) != EOF)
    {
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= n; j++)
            {
                scanf("%d",&a);
                mx[i][j][0] = mi[i][j][0] = a ;
            }
        rmqinit();
        while(q--)
        {
            scanf("%d%d", &a, &c) ;
            int rx = a + b - 1;
            if(rx > n) rx = n;
            int ry = c + b - 1;
            if(ry > n) ry = n;
            printf("%d\n", rmqmax(a, c, rx, ry) - rmqmin(a, c, rx, ry)) ;
        }
    }
    return 0;
}

查询是O(1)的那种 仅限于正方形

#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <cstdio>
#include <cmath>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <stack>
#define eps 1e-5
#define MAXN 255
#define MAXM 111111
#define INF 1000000000
using namespace std;
int mx[MAXN][MAXN][8], mi[MAXN][MAXN][8];
int n, b, q;
int Get_mx(int x, int y, int p)
{
    int ret = -INF;
    ret = max(ret, mx[x][y][p]);
    if (x + (1 << p) <= n) ret = max(ret, mx[x + (1 << p)][y][p]);
    if (y + (1 << p) <= n) ret = max(ret, mx[x][y + (1 << p)][p]);
    if ((x + (1 << p) <= n) && (y + (1 << p) <= n)) ret = max(ret, mx[x + (1 << p)][y + (1 << p)][p]);
    return ret;
}
int Get_mi(int x, int y, int p)
{
    int ret = INF;
    ret = min(ret, mi[x][y][p]);
    if (x + (1 << p) <= n) ret = min(ret, mi[x + (1 << p)][y][p]);
    if (y + (1 << p) <= n) ret = min(ret, mi[x][y + (1 << p)][p]);
    if ((x + (1 << p) <= n) && (y + (1 << p) <= n)) ret = min(ret, mi[x + (1 << p)][y + (1 << p)][p]);
    return ret;
}
void rmqinit()
{
    int l = int(log(n * 1.0) / log(2.0));
    for (int i = 1; i <= l; i++)
        for (int j = 1; j <= n; j++)
            for (int k = 1; k <= n; k++)
            {
                mx[j][k][i] = Get_mx(j, k, i - 1);
                mi[j][k][i] = Get_mi(j, k, i - 1);
            }
}
int rmqmax(int x, int y, int b)
{
    int p =  int(log(b * 1.0) / log(2.0));
    int ret = -INF;
    ret = max(ret, mx[x][y][p]);
    if (x + b - (1 << p) <= n) ret = max(ret, mx[x + b - (1 << p)][y][p]);
    if (y + b - (1 << p) <= n) ret = max(ret, mx[x][y + b - (1 << p)][p]);
    if ((x + b - (1 << p) <= n) && (y + b - (1 << p) <= n)) ret = max(ret, mx[x + b - (1 << p)][y + b - (1 << p)][p]);
    return ret;
}
int rmqmin(int x, int y, int b)
{
    int p =  int(log(b * 1.0) / log(2.0));
    int ret = INF;
    ret = min(ret, mi[x][y][p]);
    if (x + b - (1 << p) <= n) ret = min(ret, mi[x + b - (1 << p)][y][p]);
    if (y + b - (1 << p) <= n) ret = min(ret, mi[x][y + b - (1 << p)][p]);
    if ((x + b - (1 << p) <= n) && (y + b - (1 << p) <= n)) ret = min(ret, mi[x + b - (1 << p)][y + b - (1 << p)][p]);
    return ret;
}
int main()
{
    int val;
    scanf("%d%d%d", &n, &b, &q);
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= n; j++)
        {
            scanf("%d", &val);
            mx[i][j][0] = mi[i][j][0] = val;
        }
    rmqinit();
    int x, y;
    while(q--)
    {
        scanf("%d%d", &x, &y);
        printf("%d\n", rmqmax(x, y, b) - rmqmin(x, y, b));
    }
    return 0;
}


然后就是推广到矩形的写法 比较麻烦 占用的内存也比较大

#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <cstdio>
#include <cmath>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <stack>
#define eps 1e-5
#define MAXN 255
#define MAXM 111111
#define INF 1000000000
using namespace std;
int n, b, k, m;
int mi[MAXN][MAXN][10][10];
int mx[MAXN][MAXN][10][10];
int val[MAXN][MAXN];
void init()
{
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
            mi[i][j][0][0] = mx[i][j][0][0] = val[i][j];
    int kn = (int)(log((double)n) / log(2.0));
    int km = (int)(log((double)m) / log(2.0));
    for(int i = 0; i <= kn; ++i)
        for(int j = 0; j <= km; ++j)
        {
            if (!i && !j) continue;
            for(int r = 1; r + (1 << i) - 1 <= n; r++)
                for(int c = 1; c + (1 << j) - 1 <= m; c++)
                {
                    if (!i)
                    {
                        mi[r][c][i][j] = min(mi[r][c][i][j - 1], mi[r][c + (1 << (j - 1))][i][j - 1]);
                        mx[r][c][i][j] = max(mx[r][c][i][j - 1], mx[r][c + (1 << (j - 1))][i][j - 1]);
                    }
                    else
                    {
                        mi[r][c][i][j] = min(mi[r][c][i - 1][j], mi[r + (1 << (i - 1))][c][i - 1][j]);
                        mx[r][c][i][j] = max(mx[r][c][i - 1][j], mx[r + (1 << (i - 1))][c][i - 1][j]);
                    }
                }
        }
}
int rmqmax(int r1, int c1, int r2, int c2)
{
    int kr = (int)(log((double)r2 - r1 + 1) / log(2.0));
    int kc = (int)(log((double)c2 - c1 + 1) / log(2.0));
    int t1 = mx[r1][c1][kr][kc];
    int t2 = mx[r2 - (1 << kr) + 1][c1][kr][kc];
    int t3 = mx[r1][c2 - (1 << kc) + 1][kr][kc];
    int t4 = mx[r2 - (1 << kr) + 1][c2 - (1 << kc) + 1][kr][kc];
    return max(max(t1, t2), max(t3, t4));
}
int rmqmin(int r1, int c1, int r2, int c2)
{
    int kr = (int)(log((double)r2 - r1 + 1) / log(2.0));
    int kc = (int)(log((double)c2 - c1 + 1) / log(2.0));
    int m1 = mi[r1][c1][kr][kc];
    int m2 = mi[r2 - (1 << kr)+1][c1][kr][kc];
    int m3 = mi[r1][c2 - (1 << kc) + 1][kr][kc];
    int m4 = mi[r2 - (1 << kr) + 1][c2 - (1 << kc) + 1][kr][kc];
    return min(min(m1, m2), min(m3, m4));
}
int main()
{
    scanf("%d%d%d", &n, &m, &k);
    for(int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
            scanf("%d", &val[i][j]);
    init();
    int r1, c1, r2, c2;
    for (int i = 0; i < k; ++i)
    {
        scanf("%d%d%d%d", &r1, &c1, &r2, &c2);
        printf("%d\n", rmqmax(r1, c1, r2, c2));
    }
    return 0;
}


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics