[SDOI2010]粟粟的书架
前50分就开两个数组,一个sum[i][j][k],表示1,1到i,j大于k的和,num[i][j][k]表示个数,二分一下就好
后50分用主席树,主席树上二分
# include <bits/stdc++.h>
# define RG register
# define IL inline
# define Fill(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long ll;
const int _(6e6 + 10);
IL ll Read(){
char c = '%'; ll x = 0, z = 1;
for(; c > '9' || c < '0'; c = getchar()) if(c == '-') z = -1;
for(; c >= '0' && c <= '9'; c = getchar()) x = x * 10 + c - '0';
return x * z;
}
int R, C, M;
namespace Score1{
int p[210][210], sum[210][210][1010], num[210][210][1010], Max;
IL void Work(){
for(RG int i = 1; i <= R; ++i)
for(RG int j = 1; j <= C; ++j)
p[i][j] = Read(), Max = max(p[i][j], Max);
for(RG int k = 1; k <= Max; ++k)
for(RG int i = 1; i <= R; ++i)
for(RG int j = 1; j <= C; ++j){
sum[i][j][k] = sum[i - 1][j][k] + sum[i][j - 1][k] - sum[i - 1][j - 1][k];
num[i][j][k] = num[i - 1][j][k] + num[i][j - 1][k] - num[i - 1][j - 1][k];
if(p[i][j] >= k) ++num[i][j][k], sum[i][j][k] += p[i][j];
}
while(M--){
RG int x1, y1, x2, y2, h, l = 1, r = Max, ans = 0;
x1 = Read(); y1 = Read(); x2 = Read(); y2 = Read(); h = Read();
while(l <= r){
RG int mid = (l + r) >> 1;
RG int calc = sum[x2][y2][mid] - sum[x2][y1 - 1][mid] - sum[x1 - 1][y2][mid] + sum[x1 - 1][y1 - 1][mid];
if(calc >= h) ans = mid, l = mid + 1;
else r = mid - 1;
}
if(!ans){ puts("Poor QLW"); continue; }
RG int s = sum[x2][y2][ans] - sum[x2][y1 - 1][ans] - sum[x1 - 1][y2][ans] + sum[x1 - 1][y1 - 1][ans];
RG int f = num[x2][y2][ans] - num[x2][y1 - 1][ans] - num[x1 - 1][y2][ans] + num[x1 - 1][y1 - 1][ans];
f -= (s - h) / ans;
printf("%d\n", f);
}
}
}
namespace Score2{
int rt[_], sz[_], sum[_], ls[_], rs[_], cnt;
IL void Build(RG int &x, RG int l, RG int r){
x = ++cnt;
if(l == r) return;
RG int mid = (l + r) >> 1;
Build(ls[x], l, mid); Build(rs[x], mid + 1, r);
}
IL void Modify(RG int &x, RG int l, RG int r, RG int v){
sz[++cnt] = sz[x]; sum[cnt] = sum[x]; ls[cnt] = ls[x]; rs[cnt] = rs[x];
x = cnt; sz[cnt]++; sum[x] += v;
if(l == r) return;
RG int mid = (l + r) >> 1;
if(v <= mid) Modify(ls[x], l, mid, v);
else Modify(rs[x], mid + 1, r, v);
}
IL int Query(RG int A, RG int B, RG int l, RG int r, RG int h){
if(l == r) return (h + l - 1) / l;
RG int mid = (l + r) >> 1, s = sum[rs[A]] - sum[rs[B]];
if(s >= h) return Query(rs[A], rs[B], mid + 1, r, h);
return Query(ls[A], ls[B], l, mid, h - s) + sz[rs[A]] - sz[rs[B]];
}
IL void Work(){
Build(rt[0], 1, 1000);
for(RG int i = 1, a; i <= C; ++i) a = Read(), rt[i] = rt[i - 1], Modify(rt[i], 1, 1000, a);
while(M--){
RG int h, l, r;
Read(); l = Read(); Read(); r = Read(); h = Read();
if(sum[rt[r]] - sum[rt[l - 1]] < h) puts("Poor QLW");
else printf("%d\n", Query(rt[r], rt[l - 1], 1, 1000, h));
}
}
}
int main(RG int argc, RG char *argv[]){
R = Read(); C = Read(); M = Read();
if(R > 1) Score1::Work();
else Score2::Work();
return 0;
}