「国家集训队」矩阵乘法
「国家集训队」矩阵乘法
传送门
还是静态区间第 \(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;
}