「国家集训队」矩阵乘法
传送门
还是静态区间第 \(k\) 小,只不过变成二维平面而不是序列了。
整体二分做法:就把树状数组改成二维的就好了。。。
还写主席树的话就不太好写了。。。
参考代码:
#include <cstdio> #define rg register #define file(x) freopen(x".in", "r", stdin), freopen(x".out", "w", stdout) template < class T > inline void read(T& s) { s = 0; int f = 0; char c = getchar(); while ('0' > c || c > '9') f |= c == '-', c = getchar(); while ('0' <= c && c <= '9') s = s * 10 + c - 48, c = getchar(); s = f ? -s : s; } const int _ = 502, __ = 310002; int n, q, res[__], tr[_][_]; int num; struct node { int x, y, v, id, a, b, c, d, k; } t[__], tt1[__], tt2[__]; inline void update(int x, int y, int v) { for (rg int i = x; i <= n; i += i & -i) for (rg int j = y; j <= n; j += j & -j) tr[i][j] += v; } inline int query(int x, int y) { int res = 0; for (rg int i = x; i; i -= i & -i) for (rg int j = y; j; j -= j & -j) res += tr[i][j]; return res; } inline void solve(int ql, int qr, int l, int r) { if (ql > qr || l > r) return ; if (l == r) { for (rg int i = ql; i <= qr; ++i) if (t[i].id) res[t[i].id] = l; return ; } int mid = (l + r) >> 1; rg int p1 = 0, p2 = 0; for (rg int i = ql; i <= qr; ++i) { if (t[i].id == 0) { if (t[i].v <= mid) update(t[i].x, t[i].y, 1), tt1[++p1] = t[i]; else tt2[++p2] = t[i]; } else { int cnt = query(t[i].c, t[i].d) - query(t[i].a - 1, t[i].d) - query(t[i].c, t[i].b - 1) + query(t[i].a - 1, t[i].b - 1); if (cnt >= t[i].k) tt1[++p1] = t[i]; else t[i].k -= cnt, tt2[++p2] = t[i]; } } for (rg int i = 1; i <= p1; ++i) if (tt1[i].id == 0) update(tt1[i].x, tt1[i].y, -1); for (rg int i = 1; i <= p1; ++i) t[ql + i - 1] = tt1[i]; for (rg int i = 1; i <= p2; ++i) t[ql + p1 + i - 1] = tt2[i]; solve(ql, ql + p1 - 1, l, mid), solve(ql + p1, qr, mid + 1, r); } int main() { #ifndef ONLINE_JUDGE file("cpp"); #endif read(n), read(q); for (rg int i = 1; i <= n; ++i) for (rg int j = 1; j <= n; ++j) read(t[++num].v), t[num].x = i, t[num].y = j; for (rg int i = 1; i <= q; ++i) read(t[++num].a), read(t[num].b), read(t[num].c), read(t[num].d), read(t[num].k), t[num].id = i; solve(1, num, 0, 1000000000); for (rg int i = 1; i <= q; ++i) printf("%d\n", res[i]); return 0; }
来源:https://www.cnblogs.com/zsbzsb/p/12232302.html