【YBTOJ】【Luogu P1527】[國家集訓隊]矩陣乘法
阿新 • • 發佈:2021-06-12
連結:
題目大意:
二維區間第 \(k\) 小。
正文:
就是區間第 \(k\) 小的升維版,詳見 區間第 \(k\) 小。
程式碼:
const int N = 510 + 10, M = 6e4 + 10, P = 25e4 + 10; inline ll Read() { ll x = 0, f = 1; char c = getchar(); while (c != '-' && (c < '0' || c > '9')) c = getchar(); if (c == '-') f = -f, c = getchar(); while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar(); return x * f; } int n, m, tot; ll t[N][N], ans[M]; void modify(int x, int y, ll val) { for (int i = x; i <= n; i += i & -i) for (int j = y; j <= n; j += j & -j) t[i][j] += val; } int Query(int x, int y) { int ans = 0; for (int i = x; i; i -= i & -i) for (int j = y; j; j -= j & -j) ans += t[i][j]; return ans; } int query(int Lx, int Ly, int Rx, int Ry) { return Query(Rx, Ry) - Query(Lx - 1, Ry) - Query(Rx, Ly - 1) + Query(Lx - 1, Ly - 1); } struct node { int Lx, Ly, Rx, Ry, k, id; node(){ } node(int a, int b, int c, int d, int val, int i) { Lx = a, Ly = b, Rx = c, Ry = d, k = val, id = i; } }q[P + M], q1[P + M], q2[P + M]; void Solve (int l, int r, int L, int R) { if (l > r || L > R) return ; if(l == r) { for (int i = L; i <= R; i++) if(q[i].id) ans[q[i].id] = l; return ; } int mid = l + r >> 1; int n1 = 0, n2 = 0; for (int i = L; i <= R; i ++) if (q[i].id) { ll tmp = query(q[i].Lx, q[i].Ly, q[i].Rx, q[i].Ry); if (q[i].k <= tmp) q1[++n1] = q[i]; else q[i].k -= tmp, q2[++n2] = q[i]; } else if (q[i].k <= mid) modify(q[i].Lx, q[i].Ly, 1), q1[++n1] = q[i]; else q2[++n2] = q[i]; for (int i = 1; i <= n1; i++) if(!q1[i].id) modify(q1[i].Lx, q1[i].Ly, -1); for (int i = 1; i <= n1; i++) q[L + i - 1] = q1[i]; for (int i = 1; i <= n2; i++) q[L + n1 + i - 1] = q2[i]; Solve(l, mid, L, L + n1 - 1), Solve(mid + 1, r, L + n1, R); } int main() { n = Read(), m = Read(); for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) q[++tot] = node(i, j, 0, 0, Read(), 0); for (int i = 1; i <= m; i++) q[++tot].Lx = Read(), q[tot].Ly = Read(), q[tot].Rx = Read(), q[tot].Ry = Read(), q[tot].k = Read(), q[tot].id = i; Solve(0, 1e9, 1, tot); for (int i = 1; i <= m; i++) printf ("%lld\n", ans[i]); return 0; }