二维 ST POJ 2019

题目大意:给你一个n*n的矩阵,每次给你一个点(x,y),以其为左上角,宽度为b的矩阵中最小的数值和最大数值的差是多少?  一共k个询问。

思路:简单的二维st。

定义dp(i,j,k,L)表示以(i,j)为左上角,宽度为(2^k, 2^L)的区间内的最大(小)值。

//看看会不会爆int!数组会不会少了一维!
//取物问题一定要小心先手胜利的条件
#include<cstdio>
#include<cstring>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<algorithm>
#include<iostream>
#include<utility>
#include<stdlib.h>
#include<time.h>
#include<cmath>
using namespace std;
#pragma comment(linker,"/STACK:102400000,102400000")
#define LL long long
#define ALL(a) a.begin(), a.end()
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define haha printf("haha\n")
const int maxn = 250 + 5;
int dp[maxn][maxn][8][8], dp2[maxn][maxn][8][8];
int n, b, k;

void init_st(){
    for (int i = 0; (1 << i) <= n; i++){
        for (int j = 0; (1 << j) <= n; j++){
            if (i == 0 && j == 0) continue;
            for (int x = 1; x + (1 << i) - 1 <= n; x++){
                for (int y = 1; y + (1 << j) - 1 <= n; y++){
                    if (i == 0) {
                        dp[x][y][i][j] = min(dp[x][y][i][j - 1], dp[x][y + (1 << (j - 1))][i][j - 1]);
                        dp2[x][y][i][j] = max(dp2[x][y][i][j - 1], dp2[x][y + (1 << (j - 1))][i][j - 1]);
                    }
                    else {
                        dp[x][y][i][j] = min(dp[x][y][i - 1][j], dp[x + (1 << (i - 1))][y][i - 1][j]);
                        dp2[x][y][i][j] = max(dp2[x][y][i - 1][j], dp2[x + (1 << (i - 1))][y][i - 1][j]);
                    }
                }
            }
        }
    }
}

int query(int x, int y, int X, int Y){
    int maxi = 0, mini = 1e8;
    int k1 = 0, k2 = 0;
    while (1 << (1 + k1) <= X - x) k1++;
    while (1 << (1 + k2) <= Y - y) k2++;
    maxi = max(maxi, max(dp2[x][y][k1][k2], dp2[X - (1 << k1) + 1][y][k1][k2]));
    maxi = max(maxi, max(dp2[x][Y - (1 << k2) + 1][k1][k2], dp2[X - (1 << k1) + 1][Y - (1 << k2) + 1][k1][k2]));

    mini = min(mini, min(dp[x][y][k1][k2], dp[X - (1 << k1) + 1][y][k1][k2]));
    mini = min(mini, min(dp[x][Y - (1 << k2) + 1][k1][k2], dp[X - (1 << k1) + 1][Y - (1 << k2) + 1][k1][k2]));
    //printf("maxi = %d mini = %d\n", maxi, mini);
    return maxi - mini;
}

int main(){
    //while (true){
    cin >> n >> b >> k;
    for (int i = 1; i <= n; i++){
        for (int j = 1; j <= n; j++){
            scanf("%d", &dp[i][j][0][0]);
            dp2[i][j][0][0] = dp[i][j][0][0];
        }
    }
    init_st();
    for (int i = 1; i <= k; i++){
        int x, y; scanf("%d%d", &x, &y);
        int ans = query(x, y, x + b - 1, y + b - 1);
        printf("%d\n", ans);
    }
    //}
    return 0;
}

时间: 2024-10-24 21:11:22

二维 ST POJ 2019的相关文章

二维st表,一种暴力但却快速的二维RMQ利器

先上例题:[HAOI2007]理想的正方形 大部分人都用单调队列,但我不会.首先我们可以暴力枚举所有的可能的正方形,每次我们需要查询RMQ,如果用朴素的方法总复杂度就会变成N^4,你不T谁T 那怎么办,总不可能写正解吧,我们可以用二维st表,预处理N^2logN,每次O(1)查询,N^2水过. 注意,强制类型转换要用大括号括起要转换的东西,例如 (int)(log(n)/log(2)); Code: #include<iostream> #include<cstdio> #incl

POJ2019 Cornfields 二维ST表

网址:https://vjudge.net/problem/POJ-2019 题意: 给出一个矩阵,求左下角坐标为$(x,y)$,长度为$b$的正方形的包含的数的最大值和最小值. 题解: 一.二维ST表: 一维$ST$表可以快速处理一维$RMQ$问题,这次是二维问题,好,那就上二维$ST$表,构造方法和一维的类似.开一个四维数组,第一维第三维管横行,第二维第四维管纵行即可(反过来也行).然后处理完之后按照类似于一维$ST$表一样查询,查询四个小矩阵的最值就行,然后取最值,具体看代码. AC代码:

HDU2888 二维ST

以前写过一个一维的,今晚用了好久跟据那个一维的改成了二维然后做了这题 ST算法:求指定区间内的最值 一维: 设 d[i][j] 表示[i,i+1,...,i+2^j-1]这个区间内的最值然后给出的任意一个区间都可以用两个这样的区间来表示(有重叠部分)然后只需要对两个区间求一个max就ok d[i][j]可以通过递推得到 二维:设d[i][j][k][l]表示由[i,i+1,....,i+2^j-1]行和[k,k+1,....,k+2^l-1]列组成的子矩阵内的最大值,然后可以由四部分放一起表示出

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

Codeforces Round #371 (Div. 1) D - Animals and Puzzle 二维ST表 + 二分

D - Animals and Puzzle #include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define PII pair<int, int> #define PLI pair<LL, int> #define ull unsigned long long using namespace std; const in

POJ 2019 Cornfields 二维RMQ

题目来源:POJ 2019 Cornfields 题意:求正方形二维区间最大最小值的差 思路:直接二维ST搞 试模版而已 #include <cstdio> #include <algorithm> #include <cmath> using namespace std; const int maxn = 255; int dp[maxn][maxn][8][8]; int dp2[maxn][maxn][8][8]; int a[maxn][maxn]; int n

[poj2019]Cornfields(二维RMQ)

题意:给你一个n*n的矩阵,让你从中圈定一个小矩阵,其大小为b*b,有q个询问,每次询问告诉你小矩阵的左上角,求小矩阵内的最大值和最小值的差. 解题关键:二维st表模板题. 预处理复杂度:$O({n^2}\log n)$ 查询复杂度:$O(n)$ 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdlib> 5 #include<iostream>

二维RMQ

求二维ST表 for (int k=0;k<=10;k++) for (int l=0;l<=10;l++) for (int i=1;i<=n;i++) for (int j=1;j<=m;j++){ int ty=min(j+(1<<(l-1)),m+1),tx=min(n+1,i+(1<<(k-1))); if (k==0&&l==0) continue;else if (k==0) rmq[i][j][k][l]=max(rmq[i]

codeforces 713D D. Animals and Puzzle 二分+二维rmq

题目链接 给一个01矩阵, 然后每个询问给出两个坐标(x1, y1), (x2, y2). 问你这个范围内的最大全1正方形的边长是多少. 我们dp算出以i, j为右下角的正方形边长最大值. 然后用二维st表预处理出所有的最大值. 对于每个询问, 我们二分一个值mid, 查询(x1 + mid -1, y1 + mid -1), (x2, y2)这个范围内的最大值是否大于mid .如果大于的话就说明在(x1, y1), (x2, y2)范围内存在一个边长为mid的正方形. #include <bi