题意
给一个n*m的矩阵,每个位置里有一本书,每本书有一个高度,在给定的矩阵中找最少要几本书才能使高度大于等于h
思路
分情况讨论,首先对于R,C<=200:
sum[i][j][k]
表示对于子矩阵1-i ,1-j的子矩阵中有多少大于等于k值的和,cal[i][j][k]
表示对于子矩阵1-i ,1-j的子矩阵中有多少大于等于k值的个数,然后二分找最少的书.对于R=1的情况,用主席树解决.(这个代码也是借鉴别人的,写出来就很像了).洛谷题解可以多看看洛谷的题解
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=500000;
int a[210][210],[210][210][1010],cal[210][210][1010];
int n,m,q;
int get_sum(int a,int b,int c,int d,int h){
return sum[c][d][h]-sum[c][b-1][h]-sum[a-1][d][h]+sum[a-1][b-1][h];
}
int get_val(int a,int b,int c,int d,int h){
return cal[c][d][h]-cal[c][b-1][h]-cal[a-1][d][h]+cal[a-1][b-1][h];
}
int cnt=0,root[maxn];
struct node{
int l,r,ls,rs,sum,w;
}t[40*maxn];
int build(int l,int r){
int k=++cnt;
// printf("l=%d r=%d\n",l,r);
t[k].l=l,t[k].r=r;
if(l==r) return k;
int mid=l+r>>1;
t[k].ls=build(l,mid);
t[k].rs=build(mid+1,r);
return k;
}
int add(int last,int x){
int k=++cnt;
t[k]=t[last];
t[k].w++;
t[k].sum+=x;
if(t[k].l==t[k].r) return k;
int mid=t[k].l+t[k].r>>1;
if(x<=mid) t[k].ls=add(t[k].ls,x);
else t[k].rs=add(t[k].rs,x);
return k;
}
int query(int k1,int k2,int k){
if(t[k1].l==t[k1].r) return (k-1)/t[k1].l+1;
int w=t[t[k2].rs].sum-t[t[k1].rs].sum;
if(k<=w) return query(t[k1].rs,t[k2].rs,k);
else return query(t[k1].ls,t[k2].ls,k-w)+t[t[k2].rs].w-t[t[k1].rs].w;
}
int main(){
scanf("%d%d%d",&n,&m,&q);
if(n!=1){
int maxx=-1;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&a[i][j]),maxx=max(maxx,a[i][j]);
for(int k=1;k<=maxx;k++)
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(a[i][j]>=k){
sum[i][j][k]=sum[i-1][j][k]+sum[i][j-1][k]-sum[i-1][j-1][k]+a[i][j];
cal[i][j][k]=cal[i-1][j][k]+cal[i][j-1][k]-cal[i-1][j-1][k]+1;
}
else {
sum[i][j][k]=sum[i-1][j][k]+sum[i][j-1][k]-sum[i-1][j-1][k];
cal[i][j][k]=cal[i-1][j][k]+cal[i][j-1][k]-cal[i-1][j-1][k];
}
}
}
while(q--){
int a,b,c,d,h;scanf("%d%d%d%d%d",&a,&b,&c,&d,&h);
if(get_sum(a,b,c,d,1)<h){
printf("Poor QLW\n");
continue;
}
int l=1,r=maxx;
while(l<r){
int mid=(l+r+1)>>1;
if(get_sum(a,b,c,d,mid)>=h) l=mid;
else r=mid-1;
}
int ans=get_val(a,b,c,d,l)-(get_sum(a,b,c,d,l)-h)/l;
printf("%d\n",ans);
}
}
else{
cnt=0;
root[0]=1;
build(1,1000);
for(int i=1,x;i<=m;i++){
scanf("%d",&x);
root[i]=cnt+1;
add(root[i-1],x);
}
while(q--){
int a,b,c,d,h;scanf("%d%d%d%d%d",&a,&b,&c,&d,&h);
b--;
if(t[root[d]].sum-t[root[b]].sum<h) printf("Poor QLW\n");
else printf("%d\n",query(root[b],root[d],h));
}
}
//system("pause");
}