# bzoj1926: [Sdoi2010]粟粟的书架

### 题目链接

bzoj1926: [Sdoi2010]粟粟的书架

### 题解

sum[i][j][k] 维护维护矩形（1,1）（i,j）中比k大的数和为多少

### 代码

#include<cstdio>
#include<cstring>
#include<algorithm>

using std::max;
int R,C,m;
int x = 0,f = 1;
char c = getchar ();
while(c < '0' || c > '9'){if(c == '-') f = -1; c = getchar();}
while(c <= '9' && c >= '0') x = x * 10 + c - '0',c = getchar();
return x*f;
}
namespace Solve_1 {
#define maxn 207
int a[maxn][maxn];
int num[maxn][maxn][1007],sum[maxn][maxn][1007];
int Max = 0;
int  get_sum(int a,int b,int c,int d,int v) {
return sum[c][d][v] - sum[a][d][v] - sum[c][b][v] + sum[a][b][v];
}
int  get_num(int a,int b,int c,int d,int v) {
return num[c][d][v] - num[a][d][v] - num[c][b][v] + num[a][b][v];
}
int Get_Ans(int a,int b,int c,int d,int k,int need) {
int ret = get_num(a,b,c,d,k+1);
need -= get_sum(a,b,c,d,k+1);
if(need>=0) {
int num = need / k;
ret += num;
need -= num * k;if(need > 0)ret++,need -= k;
}
return ret;
}
bool judge (int a,int b,int c,int d,int mid,int h) {
//printf("%d\n",get_sum(a,b,c,d,mid));
return get_sum(a,b,c,d,mid) > h ? true : false;
}
void work_Main() {
memset(sum,0,sizeof sum);
memset(num,0,sizeof num);
for(int i = 1;i <= R;++ i)
for(int j = 1;j <= C;++ j)
a[i][j] = read(),Max = max (Max,a[i][j]);
/*for(int i = 1;i <= R;++i)
for(int j = 1;j <= C;++ j)
for(int k = 1;k <= Max;++k)
sum[i][j][k]= num[i][j][k] = 0;*/
for(int k = 0;k <= Max;++ k)
for(int i = 1;i <= R;++ i)
for(int j = 1;j <= C;++ j) {
//printf("%d\n",sum[i][j][k]);
num[i][j][k] = num[i-1][j][k] + num[i][j-1][k] - num[i-1][j-1][k] + (a[i][j] >= k ?  1: 0);
sum[i][j][k] = sum[i-1][j][k] + sum[i][j-1][k] - sum[i-1][j-1][k] + (a[i][j] >= k ? a[i][j] : 0);
}
for(int a,b,c,d,h;m --;) {
if(get_sum(a,b,c,d,0) < h) {
puts("Poor QLW");continue;
}
int l = 1,r = Max,ans = 0;
while(l <= r) {
int mid = l + r >> 1;
if(judge(a,b,c,d,mid,h)) l = mid + 1,ans = mid;
else r = mid - 1;
}
if(!ans) ans = 1;
if(ans) printf("%d\n",Get_Ans(a,b,c,d,ans,h));
}
}
#undef maxn
}
namespace Solve_2{
#define maxn 500007
#define lc t[x].ch[0]
#define rc t[x].ch[1]
int a[maxn],tot = 0;
int root[maxn];
struct ChairMan_Tree {
int ch[2],sum,sz;
ChairMan_Tree() {
sum=sz=ch[1]=ch[0]=0;
}
};
ChairMan_Tree t[maxn << 4];
int Max = 0;
void update(int x) {
t[x].sum = t[lc].sum + t[rc].sum;
}
void Insert(int pre,int &x,int l,int r,int p) {
t[x = ++ tot].sz = t[pre].sz + 1,t[x].sum = t[pre].sum;
if(l == r) {
t[x].sum += p; return ;
}
int mid = l + r >> 1;
if( p<=mid ) rc = t[pre].ch[1],Insert(t[pre].ch[0],lc,l,mid,p);
else lc = t[pre].ch[0],Insert(t[pre].ch[1],rc,mid + 1,r,p);
update(x);
}
int query(int pre,int x,int l,int r,int k) {
if(t[x].sz <= t[pre].sz + k) return t[x].sum - t[pre].sum;
if(l == r) return (t[x].sum - t[pre].sum) / (t[x].sz - t[pre].sz) *k;
int mid = l + r >> 1;
if(t[rc].sz >= t[t[pre].ch[1]].sz + k) return query(t[pre].ch[1],rc,mid + 1,r,k);
else return query(t[pre].ch[0],lc,l,mid,k - t[rc].sz + t[t[pre].ch[1]].sz) + t[rc].sum - t[t[pre].ch[1]].sum;
}
void Work_Main() {
Max = 1000;
for(int i = 1;i<= C;++ i)
for(int i = 1;i <= C;++ i) Insert(root[i-1],root[i],1,Max,a[i]);
for(int l,r,a,b,c,d,h;m --;) {
l = 1,r = d - b + 1;
while(l < r) {
int mid = l + r >> 1;
if(query(root[b],root[d],1,Max,mid) >= h) r = mid;
else l = mid + 1;
}
if(r == d - b + 1) puts("Poor QLW");
else printf("%d\n",l);
}
}
}
int main() {