Description
Solution
观察到数据范围:
对于 \(50\%\) 的数据,满足 \(R,C \leq 200\)
另有 \(50\%\) 的数据,满足 \(R = 1, C \leq 5 \times 10^5\)
……
明显要进行数据分治了。。
Subtask_1
直接暴力计算二维前缀和,然后二分查询即可。
具体来说,枚举一个 \(k (1 \leq k \leq 1000)\),然后把 \(\geq k\) 的数赋值为 1,\(< k\) 的数赋值为 0。
预处理时间复杂度:\(O(1000nm)\)
查询时间复杂度:\(O(q\log 1000)\)
Subtask_2
这时就变成了在一个一维数组上查询,那么就一个主席树板子。
不多解释了,直接看代码吧。
Code
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
namespace IO{
inline int read(){
int x = 0;
char ch = getchar();
while(!isdigit(ch)) ch = getchar();
while(isdigit(ch)) x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x;
}
template <typename T> inline void write(T x){
if(x < 0) putchar('-'), x = -x;
if(x > 9) write(x / 10);
putchar(x % 10 + '0');
}
}
using namespace IO;
const int V = 1000;
int n, m, q;
namespace Subtask_1{
int a[210][210], sum[210][210][V + 10], cnt[210][210][V + 10];
inline void prework(){
int mx = 0;
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
a[i][j] = read(), mx = max(mx, a[i][j]);
for(int k = 1; k <= mx; ++k)
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j){
sum[i][j][k] = sum[i][j - 1][k] + sum[i - 1][j][k] - sum[i - 1][j - 1][k] + (a[i][j] >= k ? a[i][j] : 0);
cnt[i][j][k] = cnt[i][j - 1][k] + cnt[i - 1][j][k] - cnt[i - 1][j - 1][k] + (a[i][j] >= k);
}
}
inline int Sum(int x1, int y1, int x2, int y2, int k){
return sum[x2][y2][k] - sum[x2][y1 - 1][k] - sum[x1 - 1][y2][k] + sum[x1 - 1][y1 - 1][k];
}
inline int Cnt(int x1, int y1, int x2, int y2, int k){
return cnt[x2][y2][k] - cnt[x2][y1 - 1][k] - cnt[x1 - 1][y2][k] + cnt[x1 - 1][y1 - 1][k];
}
inline int solve(){
prework();
while(q--){
int x1 = read(), y1 = read(), x2 = read(), y2 = read(), h = read();
if(Sum(x1, y1, x2, y2, 1) < h){
puts("Poor QLW");
continue;
}
int l = 1, r = V, res = 0;
while(l <= r){
int mid = (l + r) >> 1;
if(Sum(x1, y1, x2, y2, mid) >= h) res = mid, l = mid + 1;
else r = mid - 1;
}
write(Cnt(x1, y1, x2, y2, res) - (Sum(x1, y1, x2, y2, res) - h) / res), puts("");
}
return 0;
}
}
namespace Subtask_2{
#define ls(x) t[x].l
#define rs(x) t[x].r
const int N = 5e5 + 10;
struct Tree{
int sum, cnt, l, r;
}t[N << 6];
int root[N << 6], cnt, H;
int a[N], b[N];
inline int update(int pre, int l, int r, int x){
int rt = ++cnt;
ls(rt) = ls(pre), rs(rt) = rs(pre), t[rt].sum = t[pre].sum + x, t[rt].cnt = t[pre].cnt + 1;
if(l == r) return rt;
int mid = (l + r) >> 1;
if(x <= mid) ls(rt) = update(ls(pre), l, mid, x);
else rs(rt) = update(rs(pre), mid + 1, r, x);
return rt;
}
inline int query(int L, int R, int h, int l, int r){
if(l == r) return (h - 1) / l + 1;// ceil(h / l) 还需要的高度为 h,那么需要 ceil(h / l) 本书
int Sum = t[rs(R)].sum - t[rs(L)].sum, Cnt = t[rs(R)].cnt - t[rs(L)].cnt;
int mid = (l + r) >> 1;
if(h <= Sum) return query(rs(L), rs(R), h, mid + 1, r);
else return H -= Sum, Cnt + query(ls(L), ls(R), h - Sum, l, mid);
}
inline int solve(){
for(int i = 1; i <= m; ++i){
int x = read();
root[i] = update(root[i - 1], 1, V, x);
}
while(q--){
int x1 = read(), y1 = read(), x2 = read(), y2 = read(), h = read(), H = h;
if(t[root[y2]].sum - t[root[y1 - 1]].sum < h) puts("Poor QLW");
else write(query(root[y1 - 1], root[y2], h, 1, V)), puts("");
}
return 0;
}
}
int main(){
n = read(), m = read(), q = read();
if(n > 1) Subtask_1 :: solve();
else Subtask_2 :: solve();
return 0;
}
\[\_EOF\_
\]