# 1926: [Sdoi2010]粟粟的书架

## 1926: [Sdoi2010]粟粟的书架

Time Limit: 30 Sec   Memory Limit: 552 MB
Submit: 666   Solved: 254
[ Submit][ Status][ Discuss]

## Description

rmen 的文章。粟粟家中有一个 R行C 列的巨型书架，书架的每一个位置都摆有一本书，上数第i 行、左数第j 列

y2i－y1i＋1﹚本书中挑选若干本垫在脚下，摘取苹果。粟粟每次取书时都能及时放回原位，并且她的书架不会再

5 5 7
14 15 9 26 53
58 9 7 9 32
38 46 26 43 38
32 7 9 50 28
8 41 9 7 17
1 2 5 3 139
3 1 5 5 399
3 3 4 5 91
4 1 4 1 33
1 3 5 4 185
3 3 4 3 23
3 1 3 3 108

6
15
2
Poor QLW
9
1
3

## Source

[ Submit][ Status][ Discuss]

﻿

fi,j,k:从(1,1)到(i,j)的矩形里，大于等于k的数字的总和

gi,j,k:从(1,1)到(i,j)的矩形里，大于等于k的数字的个数

#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#include<bitset>
#include<algorithm>
#include<cstring>
#include<map>
#include<stack>
#include<set>
#include<cmath>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;

const int maxn = 5E5 + 50;
const int T = 20;
const int N = 202;
const int M = 1010;

int R,C,q,cnt,f[N][N][M],g[N][N][M],root[maxn]
,lc[maxn*T],rc[maxn*T],c[maxn*T],t[maxn*T];

bool Judge(int r1,int c1,int r2,int c2,int k,int h)
{
return f[r2][c2][k] - f[r1-1][c2][k] - f[r2][c1-1][k] + f[r1-1][c1-1][k] >= h;
}

void Print(int r1,int c1,int r2,int c2,int k,int h)
{
int z = k + 1;
int ans = g[r2][c2][z] - g[r1-1][c2][z] - g[r2][c1-1][z] + g[r1-1][c1-1][z];
int res = f[r2][c2][z] - f[r1-1][c2][z] - f[r2][c1-1][z] + f[r1-1][c1-1][z];
res = h - res;
int Add = res / k;
if (res % k != 0) ++Add;
}

int Insert(int o,int l,int r,int k)
{
int ret = ++cnt;
c[ret] = c[o] + k;
t[ret] = t[o] + 1;
if (l == r) return ret;
int mid = (l + r) >> 1;
if (k <= mid) rc[ret] = rc[o],lc[ret] = Insert(lc[o],l,mid,k);
else lc[ret] = lc[o],rc[ret] = Insert(rc[o],mid+1,r,k);
return ret;
}

int Query(int o1,int o2,int l,int r,int h)
{
int tot = c[o2] - c[o1];
if (tot < h) return -1;
if (l == r) {
int ret = h / l;
if (h % l != 0) ++ret;
return ret;
}
int ret,res,mid = (l + r) >> 1;
res = c[rc[o2]] - c[rc[o1]];
if (res >= h) return Query(rc[o1],rc[o2],mid+1,r,h);
ret = t[rc[o2]] - t[rc[o1]];
return ret + Query(lc[o1],lc[o2],l,mid,h - res);
}

int getint()
{
char ch = getchar();
int ret = 0;
while (ch < '0' || '9' < ch) ch = getchar();
while ('0' <= ch && ch <= '9')
ret = ret*10 + ch - '0',ch = getchar();
return ret;
}

int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#endif

R = getint();
C = getint();
q = getint();
if (R > 1) {
for (int i = 1; i <= R; i++)
for (int j = 1; j <= C; j++) {
int x = getint();
for (int k = 1; k <= x; k++) {
f[i][j][k] = f[i-1][j][k] + f[i][j-1][k] - f[i-1][j-1][k] + x;
g[i][j][k] = g[i-1][j][k] + g[i][j-1][k] - g[i-1][j-1][k] + 1;
}
for (int k = x + 1; k <= 1000; k++) {
f[i][j][k] = f[i-1][j][k] + f[i][j-1][k] - f[i-1][j-1][k];
g[i][j][k] = g[i-1][j][k] + g[i][j-1][k] - g[i-1][j-1][k];
}
}

while (q--) {
int r1 = getint(),c1 = getint();
int r2 = getint(),c2 = getint();
int h = getint();
int l = 0,r = 1001;
while (r - l > 1) {
int mid = (l + r) >> 1;
if (Judge(r1,c1,r2,c2,mid,h)) l = mid;
else r = mid;
}
if (Judge(r1,c1,r2,c2,r,h)) Print(r1,c1,r2,c2,r,h);
else if (Judge(r1,c1,r2,c2,l,h)) Print(r1,c1,r2,c2,l,h);
else puts("Poor QLW");
}
}
else {
for (int i = 1; i <= C; i++) {
int x = getint();
root[i] = Insert(root[i-1],1,1000,x);
}
while (q--) {
int r1 = getint(),c1 = getint();
int r2 = getint(),c2 = getint();
int h = getint();
int ans = Query(root[c1-1],root[c2],1,1000,h);
if (ans != -1) printf("%d\n",ans);
else puts("Poor QLW");
}
}
return 0;
}

01-08 65
04-07 962

01-07 158
03-09 751
07-10 99
09-12 33