二维 ST POJ 2019
题目大意:给你一个n*n的矩阵,每次给你一个点(x,y),以其为左上角,宽度为b的矩阵中最小的数值和最大数值的差是多少? 一共k个询问。
思路:简单的二维st。
定义dp(i,j,k,L)表示以(i,j)为左上角,宽度为(2^k, 2^L)的区间内的最大(小)值。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//看看会不会爆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; }