题目链接
题解
看数据范围,发现这是两道题......0.5倍经验
对于R,C <= 200
前缀和+二分
前缀num[i][j][k]维护矩形(1,1)(i,j)中比k大的数有几个
sum[i][j][k] 维护维护矩形(1,1)(i,j)中比k大的数和为多少
在矩形中二分到k+1最后暴力填k
对于第二问变成了序列
二分取几个数(k)+主席树,用主席树维护权值,在主席树中取最大的k个数查看时否满足
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using std::max;
int R,C,m;
inline int read () {
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
",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
",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 --;) {
a = read() -1 ,b = read() -1,c = read(),d = read(),h = read();
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
",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)
a[i] = read();//,Max = max(a[i],Max);
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 --;) {
a = read(),b = read() -1,c = read(),d = read(),h = read();
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
",l);
}
}
}
int main() {
R=read(),C=read(),m=read();
if(R!=1) Solve_1::work_Main();
else Solve_2::Work_Main();
}