ZOJ 2859 Matrix Searching 二维线段树 || 二维RMQ
2017-08-08 20:51
477 查看
题目:
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1859题意:
给定一个n*n的矩阵,有m个询问, 每个询问给出一个子矩阵的左上角和右下角坐标,问这个子矩阵内的最小值。思路:
用二维线段树和二维RMQ都可以,没什么好说的。另外这个题数据少时限长,直接建n棵线段树都可以轻松水过,更暴力的方法也许也能过,大力出奇迹二维线段树:
#include <bits/stdc++.h> using namespace std; const int N = 300 + 10, INF = 0x3f3f3f3f; int n; int minv[N<<2][N<<2]; void push_upy(int ky, int kx) { minv[kx][ky] = min(minv[kx][ky<<1], minv[kx][ky<<1|1]); } void push_upx(int ky, int kx) { minv[kx][ky] = min(minv[kx<<1][ky], minv[kx<<1|1][ky]); } void buildy(int L, int R, int ky, int kx, int f) { if(L == R) { if(f) scanf("%d", &minv[kx][ky]); else push_upx(ky, kx); return; } int mid = (L + R) >> 1; buildy(L, mid, ky << 1, kx, f); buildy(mid + 1, R, ky << 1|1, kx, f); push_upy(ky, kx); } void buildx(int L, int R, int kx) { if(L == R) { buildy(1, n, 1, kx, 1); return; } int mid = (L + R) >> 1; buildx(L, mid, kx << 1); buildx(mid + 1, R, kx << 1|1); buildy(1, n, 1, kx, 0); } int queryy(int ly, int ry, int L, int R, int ky, int kx) { if(ly <= L && R <= ry) return minv[kx][ky]; int mid = (L + R) >> 1, ans = INF; if(ly <= mid) ans = min(ans, queryy(ly, ry, L, mid, ky << 1, kx)); if(ry > mid) ans = min(ans, queryy(ly, ry, mid + 1, R, ky << 1|1, kx)); return ans; } int queryx(int lx, int rx, int ly, int ry, int L, int R, int kx) { if(lx <= L && R <= rx) return queryy(ly, ry, 1, n, 1, kx); int mid = (L + R) >> 1, ans = INF; if(lx <= mid) ans = min(ans, queryx(lx, rx, ly, ry, L, mid, kx << 1)); if(rx > mid) ans = min(ans, queryx(lx, rx, ly, ry, mid + 1, R, kx << 1|1)); return ans; } int main() { int t, m; scanf("%d", &t); while(t--) { scanf("%d", &n); buildx(1, n, 1); scanf("%d", &m); int x1, y1, x2, y2; for(int i = 1; i <= m; i++) { scanf("%d%d%d%d", &x1, &y1, &x2, &y2); printf("%d\n", queryx(x1, x2, y1, y2, 1, n, 1)); } } return 0; }
二维RMQ:
#include <bits/stdc++.h> using namespace std; const int N = 300 + 5, INF = 0x3f3f3f3f; int a , dp [9][9]; void ST(int n, int m) { for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) dp[i][j][0][0] = a[i][j]; for(int i = 0; (1<<i) <= n; i++) for(int j = 0; (1<<j) <= m; j++) { if(i == 0 && j == 0) continue; for(int row = 1; row <= n - (1<<i) + 1; row++) for(int col = 1; col <= m - (1<<j) + 1; col++) if(i == 0) dp[row][col][i][j] = min(dp[row][col][i][j-1], dp[row][col+(1<<(j-1))][i][j-1]); else dp[row][col][i][j] = min(dp[row][col][i-1][j], dp[row+(1<<(i-1))][col][i-1][j]); } } int RMQ(int x1, int y1, int x2, int y2) { int kx = log(x2 - x1 + 1.0) / log(2.0); int ky = log(y2 - y1 + 1.0) / log(2.0); int t1 = dp[x1][y1][kx][ky]; int t2 = dp[x2-(1<<kx)+1][y1][kx][ky]; int t3 = dp[x1][y2-(1<<ky)+1][kx][ky]; int t4 = dp[x2-(1<<kx)+1][y2-(1<<ky)+1][kx][ky]; return min(min(t1, t2), min(t3, t4)); } int main() { int t, n, m; scanf("%d", &t); while(t--) { scanf("%d", &n); for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) scanf("%d", &a[i][j]); ST(n, n); int x1, y1, x2, y2; scanf("%d", &m); while(m--) { scanf("%d%d%d%d", &x1, &y1, &x2, &y2); int ans = RMQ(x1, y1, x2, y2); printf("%d\n", ans); } } return 0; }
相关文章推荐
- ZOJ 2859 二维RMQ 二维线段树(树套树)
- ZOJ 2859 二维RMQ
- ZOJ 2859 二维线段树
- ZOJ 题目2859 Matrix Searching(二维RMQ)
- ZOJ 2859 二维RMQ(模板)
- ZOJ2859-----二维的RMQ
- ZOJ-2859 Matrix Searching (二维线段树)
- ZOJ 2859 Matrix Searching 二维rmq
- ZOJ 2859 Matrix Searching(二维线段树)
- ZOJ 2859 二维线段树
- ZOJ 2859 Matrix Searching(二维RMQ)
- ZOJ 2859 二维RMQ(模板)
- zoj 2859 二维线段树 插点求线
- zoj 2859(二维RMQ)
- zoj 2859(二维线段树)
- ZOJ 题目2859 Matrix Searching(二维RMQ)
- ZOJ 3614 Choir(二维RMQ)
- zoj 3614 二维RMQ
- zoj 3614 二维RMQ
- ZOJ 3018 Population【二维线段树四分动态建树】