bzoj2738 矩阵乘法
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2738
【题解】
整体二分,然后用二维树状数组(单点修改区间查询)统计即可。
不知道为什么跑的特别慢(可能是我的整体二分常数太大?)
# include <stdio.h> # include <string.h> # include <iostream> # include <algorithm> // # include <bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; typedef unsigned long long ull; const int M = 5e5 + 10, N = 510; const int mod = 1e9+7; # define RG register # define ST static inline int read() { int x = 0, f = 1; char ch = getchar(); while(!isdigit(ch)) { if(ch == '-') f = -1; ch = getchar(); } while(isdigit(ch)) { x = (x<<3) + (x<<1) + ch - '0'; ch = getchar(); } return x*f; } int n, Q; struct quest { int x1, y1, x2, y2, k; quest() {} quest(int x1, int y1, int x2, int y2, int k) : x1(x1), y1(y1), x2(x2), y2(y2), k(k) {} inline void set() { x1 = read(), y1 = read(), x2 = read(), y2 = read(), k = read(); } }a[M]; struct pa { int x, y, d; pa() {} pa(int x, int y, int d) : x(x), y(y), d(d) {} friend bool operator < (pa a, pa b) { return a.d < b.d; } }p[M]; int pn = 0; struct BIT { int c[N][N]; # define lb(x) (x&(-x)) inline void set(int _n) { n = _n; memset(c, 0, sizeof c); } inline void edt(int x, int y, int d) { for (int i=x; i<=n; i+=lb(i)) for (int j=y; j<=n; j+=lb(j)) c[i][j] += d; } inline int sum(int x, int y) { int ret = 0; for (int i=x; i; i-=lb(i)) for (int j=y; j; j-=lb(j)) ret += c[i][j]; return ret; } inline int sum(int x1, int y1, int x2, int y2) { return sum(x2, y2) - sum(x2, y1-1) - sum(x1-1, y2) + sum(x1-1, y1-1); } }T; int id[M], ans[M], cur[M], t1[M], t2[M]; inline void solve(int l, int r, int al, int ar, int fr) { if(al > ar) return ; if(l == r) { for (int i=al; i<=ar; ++i) ans[id[i]] = l; return ; } // printf("%d %d %d %d %d\n", l, r, al, ar, fr); int mid = l+r>>1, ed, t1n, t2n; t1n = t2n = 0; for (ed=fr; ed<=pn; ++ed) { if(p[ed].d > mid) break; T.edt(p[ed].x, p[ed].y, 1); } for (int i=al, t; i<=ar; ++i) { int x = id[i]; if((t = cur[x] + T.sum(a[x].x1, a[x].y1, a[x].x2, a[x].y2)) >= a[x].k) t1[++t1n] = x; else t2[++t2n] = x, cur[x] = t; // printf("id = %d, t = %d\n", x, t); } // printf("%d %d\n", t1n, t2n); for (int i=fr; i<ed; ++i) T.edt(p[i].x, p[i].y, -1); int tn = al-1; for (int i=1; i<=t1n; ++i) id[++tn] = t1[i]; t1n = tn; for (int i=1; i<=t2n; ++i) id[++tn] = t2[i]; solve(l, mid, al, t1n, fr); solve(mid+1, r, t1n+1, ar, ed); } int main() { int mx = 0; n = read(), Q = read(); T.set(n); for (int i=1, t; i<=n; ++i) for (int j=1; j<=n; ++j) { t = read(); mx = max(mx, t); p[++pn] = pa(i, j, t); } sort(p+1, p+pn+1); for (int i=1; i<=Q; ++i) id[i] = i, a[i].set(); solve(0, mx, 1, Q, 1); for (int i=1; i<=Q; ++i) printf("%d\n", ans[i]); return 0; }