题意:给你一个的矩阵,每次询问一个子矩形的第 k小数
输入格式:第一行有两个整数,分别表示矩阵大小 n和询问组数 q
第 2到第 (n + 1)行,每行 n个整数,表示这个矩阵。第 (i + 1)行的第 j个数表示矩阵第 i行第 j列的数ai,j
接下来 q行,每行五个整数x1,y1,x2,y2,k,表示一组询问,要求找到以(x1,y1)为左上角,(x2,y2)为右下角的子矩形中的第 k小数
输出格式:对于每组询问,输出一行一个整数表示答案。
#include<cstdio> #include<algorithm> const int N = 505; const int M = 6e4 + 5; struct Matrix{ int x, y, val; bool operator <(const Matrix &u)const{ return val < u.val; } }matrix[N * N]; struct Query{ int x1, y1, x2, y2, k; }q[M]; struct BIT{ int n, m; int c[N][N]; inline void init(int x, int y) { n = x, m = y; } inline int lowbit(int &x) { return x & -x; } void modify(int x, int y, int p){ for(int i = x; i <= n; i += lowbit(i)) for(int t = y; t <= m; t += lowbit(t)){ c[i][t] += p; } } int query(int x,int y){ int ans = 0; for(int i = x; i; i -= lowbit(i)) for(int t = y; t; t -= lowbit(t)){ ans += c[i][t]; } return ans; } int Query(Query p){ return query(p.x2, p.y2) + query(p.x1 - 1, p.y1 - 1) - query(p.x1 - 1, p.y2) - query(p.x2, p.y1 - 1); } }Tree; int n, m, tot; int ans[M], id[M], cur[M], t1[M], t2[M]; void solve(int l, int r, int ql, int qr){ // 二分值域 if(ql > qr) return ; //该值域区间没有询问 if(l == r){ for(int i = ql; i <= qr; ++i) ans[id[i]] = matrix[l].val; return ; // 找到解 } int mid = (l + r) >> 1; for(int i = l; i <= mid; ++i) Tree.modify(matrix[i].x, matrix[i].y, 1); int cl = 0, cr = 0; for(int i = ql; i <= qr; ++i){ int u = id[i]; // 当前要处理的询问 int s = cur[u] + Tree.Query(q[u]); // 加上当前区间中位于q[u]询问矩阵范围内的点 if(s >= q[u].k) t1[++cl] = u; else t2[++cr] = u, cur[u] = s; } int kk = ql - 1; for(int i = 1; i <= cl; ++i) id[++kk] = t1[i]; // 左右分组 for(int i = 1; i <= cr; ++i) id[++kk] = t2[i]; for(int i = l; i <= mid; ++i) Tree.modify(matrix[i].x, matrix[i].y, -1); solve(l, mid, ql, ql + cl - 1); solve(mid + 1, r, ql + cl, qr); } int main(){ scanf("%d%d", &n, &m); Tree.init(n, n); for(int i = 1, val; i <= n; ++i) for(int t = 1; t <= n; ++t){ scanf("%d", &val); matrix[++tot] = Matrix{i, t, val}; } std::sort(matrix + 1, matrix + 1 + tot); for(int i = 1; i <= m; ++i) id[i] = i; for(int i = 1; i <= m; ++i) scanf("%d%d%d%d%d", &q[i].x1, &q[i].y1, &q[i].x2, &q[i].y2, &q[i].k); solve(1, tot, 1, m); for(int i = 1; i <= m; ++i) printf("%d ", ans[i]); return 0; }