【LG1527】[國家集訓隊]矩陣乘法
阿新 • • 發佈:2018-12-14
【LG1527】[國家集訓隊]矩陣乘法
題面
題解
我也不知道為什麼取個這樣的名字。。。
其實就是區間\(kth\)擴充套件到二維
還是用整體二分搞啦,把樹狀陣列換成二維的
其他的基本沒有什麼差別
複雜度\(nlog^3\)
程式碼
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <vector> using namespace std; namespace IO { const int BUFSIZE = 1 << 20; char ibuf[BUFSIZE], *is = ibuf, *it = ibuf; inline char gc() { if (is == it) it = (is = ibuf) + fread(ibuf, 1, BUFSIZE, stdin); return *is++; } } inline int gi() { register int data = 0, w = 1; register char ch = 0; while (ch != '-' && (ch > '9' || ch < '0')) ch = IO::gc(); if (ch == '-') w = -1 , ch = IO::gc(); while (ch >= '0' && ch <= '9') data = data * 10 + (ch ^ 48), ch = IO::gc(); return w * data; } const int SIZE = 400005, MAX_N = 505; struct Query { int op, x, y, _x, _y, k; } q[SIZE], rq[SIZE], lq[SIZE]; void Output(int x) { printf("%d %d %d %d %d %d\n", q[x].op, q[x].x, q[x].y, q[x]._x, q[x]._y, q[x].k); } int N, M, ans[SIZE]; int c[MAX_N][MAX_N]; inline int lb(int x) { return x & -x; } void add(int x, int y, int v) { for (int i = x; i <= N; i += lb(i)) for (int j = y; j <= N; j += lb(j)) c[i][j] += v; } int sum(int x, int y) { int res = 0; for (int i = x; i > 0; i -= lb(i)) for (int j = y; j > 0; j -= lb(j)) res += c[i][j]; return res; } void Div (int lval, int rval, int st, int ed) { if (st > ed) return ; if (lval == rval) { for (int i = st; i <= ed; i++) if (q[i].op != 0) ans[q[i].op] = lval; return ; } int mid = (lval + rval) >> 1; int lt = 0, rt = 0; for (int i = st; i <= ed; i++) { int x = q[i].x, y = q[i].y; if (q[i].op == 0) { if (q[i].k <= mid) lq[++lt] = q[i], add(x, y, 1); else rq[++rt] = q[i]; } else { int _x = q[i]._x, _y = q[i]._y; int res = sum(_x, _y) - sum(x - 1, _y) - sum(_x, y - 1) + sum(x - 1, y - 1); if (q[i].k <= res) lq[++lt] = q[i]; else q[i].k -= res, rq[++rt] = q[i]; } } for (int i = st; i <= ed; i++) if (q[i].op == 0 && q[i].k <= mid) add(q[i].x, q[i].y, -1); for (int i = 1; i <= lt; i++) q[st + i - 1] = lq[i]; for (int i = 1; i <= rt; i++) q[st + lt + i - 1] = rq[i]; Div(lval, mid, st, st + lt - 1); Div(mid + 1, rval, st + lt, ed); } int main () { N = gi(), M = gi(); int cnt = 0; for (int i = 1; i <= N; i++) for (int j = 1; j <= N; j++) q[++cnt] = (Query){0, i, j, 0, 0, gi()}; for (int i = 1; i <= M; i++) q[++cnt] = (Query){i, gi(), gi(), gi(), gi(), gi()}; Div(1, 1e9, 1, cnt); for (int i = 1; i <= M; i++) printf("%d\n", ans[i]); return 0; }