湖南附中模拟day1 金坷垃

题意描述
“没有金坷垃,怎么种庄稼?”
花花家有一块田,所有庄稼排成了 N M 列。初始时,每棵庄稼都有一个自己的高度
hi;j。花花每次可以使用 1mol 的金克拉使一棵庄稼的高度增加 1。现在有 Q 个询问,花花每
次想知道最少需要使用多少 mol 的金克拉,才能使田里出现一块高度一致,大小为 ai × bi
庄稼。
其中每个询问是独立的,也就是说这次询问使用的金克拉不会影响到下一次询问。
输入格式
输入第一行包含两个正整数 N M
接下来 N 行每行包括 M 个正整数,表示每棵庄稼最初的高度 hi;j
接下来 Q 行每行包括两个正整数 ai bi
输出格式
输出共包括 Q 行,对于每个询问输出使用金克拉的最少 mol 数。
样例输入
3 4
1 8 3 4
5 2 3 1
3 6 2 2
4
1 1
2 2
2 3
3 2
样例输出
0 4
15
9

样例解释
对于第二个询问,最优方案之一为选择以下庄稼:
3 1
2 2
对于第三个询问,最优方案之一为选择以下庄稼:
5 2 3
3 6 2
对于第四个询问,最优方案之一为选择以下庄稼:
3 4
3 1
2 2
3.7 数据规模与约定
对于 50% 的数据: N; M 40
另有 20% 的数据: N; M 200
另有 20% 的数据: N; M 300
对于 100% 的数据: N; M; hi;j 1000; Q 50; 1 ai N; 1 bi M

/*
分析题目,当一块农田的位置被确定下来之后,求出其中最高的一亩田,其他的就一定要变成和他相同的高度,问题就是这个最大值不好求,我们想到了滑动窗口这个典型例题,这个求最大值的过程可以看做是一个二维的“滑动窗口”,这样先处理每一行,在处理矩阵,分别使用两次单调队列
*/
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn = 1050;
const int inf = 587654321;
int n,m,qes,h[maxn][maxn];
int q[maxn],l,r,cnt,qc[maxn],mc[maxn][maxn];
ll mx[maxn][maxn],sum[maxn][maxn];
int read(){
    char ch=getchar();
    int x=0,f=1;
    while(!(ch>='0'&&ch<='9')){if(ch=='-')f=-1;ch=getchar();};
    while(ch>='0'&&ch<='9'){x=x*10+(ch-'0');ch=getchar();};
    return x*f;
}
void update(int &x,int y){
    if(y > x) x = y;
}
void clean(){
    l = 1;
    r = 0;
    q[0] = inf;
    q[1] = -inf;
    cnt = 0;
}
void push(int x,int lm){
    q[++r] = x;
    qc[r] = 1;
    q[r+1] = -inf;
    while(q[r] >= q[r-1]){
        qc[r-1] += qc[r];
        q[r-1] = q[r];
        q[r--] = -inf;
    }
    if(++cnt > lm){
        if(--qc[l] == 0) q[l++] = inf;
    }
}
void work(int y,int x){
    for(int i = 1;i <= n;i++){
        clean();
        for(int j = 1;j <= m;j++){
            push(h[i][j],x);
            mx[i][j] = q[l];
        }
    }
    ll ans = 9876543210123LL;
    ll base = y*x;
    for(int j = x;j <= m;j++){
        clean();
        for(int i = 1;i <= n;i++){
            push(mx[i][j],y);
            if(i >= y) ans = min(ans,base * q[l] - (sum[i][j] - sum[i-y][j] - sum[i][j-x] + sum[i-y][j-x]));
        }
    }
    cout<<ans<<endl;
}
void input(){
    freopen("fertilize.in","r",stdin);
    freopen("fertilize.out","w",stdout);
    n = read();
    m = read();
    for(int i = 1;i <= n;i++){
        for(int j = 1;j <= m;j++){
            h[i][j] = read();
            sum[i][j] = sum[i][j-1] + h[i][j];
        }
    }
    for(int j = 1;j <= m;j++){
        for(int i = 1;i <= n;i++){
            sum[i][j] = sum[i-1][j] + sum[i][j];
        }
    }
    qes = read();
    int y,x;
    for(int i = 1;i <= qes;i++){
        y = read();
        x = read();
        work(y,x);
    }
}
int main(){
    input();
    return 0;
} 

 

 

posted @ 2016-10-17 20:19  ACforever  阅读(403)  评论(0编辑  收藏  举报