二维前缀和+差分

链接:https://ac.nowcoder.com/acm/contest/5158/D
来源:牛客网

牛妹为了打比赛经常不吃饭,但是牛妹非常喜欢吃豆子,她经常会吃很多很多的豆子,所以牛妹不会感觉到饿, 自然就不想吃饭了。
现在牛妹有一个 n∗m个格子的棋盘.左下角的格子坐标为 (1,1), 右上角的格子坐标为 (n,m).棋盘的每个格子都能放任意个豆子.

这时牛可乐带着一袋豆子走了过来, 打算跟牛妹分享这些豆子, 但是牛可乐并不想就这么简单的让牛妹吃到豆子, 所以牛可乐给牛妹出了一个难题.
现在牛可乐有 k 次操作,每次操作给出四个数字 x1,y1,x2,y2: 表示牛可乐会将所有满足 x1≤x≤x2,y1≤y≤y2 这两个条件的位置上放一个豆子。
牛可乐放完豆子后给出了 q次询问, 每次询问给出四个数字 x1,y1,x2,y2: 表示询问所有满足 x1≤x≤x2,y1≤y≤y2 这两个条件的位置上中总共有多少个豆子.
这个问题可难住牛妹了, 牛妹想要吃到豆子就必须答对牛可乐的所有询问。

这个题要求两次前缀和,一次前缀和是求改变后的数组,令一次的前缀和是为了o1的查询

#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=2100;
int n,m,k,q;
ll a[maxn][maxn];
ll s[maxn][maxn];
ll ans[maxn][maxn];
int main(){
    scanf("%d%d%d%d",&n,&m,&k,&q);
    for(int i=1;i<=k;i++){
        int x1,y1,x2,y2;
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
        a[x1][y1]++;
        a[x1][y2+1]--;
        a[x2+1][y1]--;
        a[x2+1][y2+1]++;
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            s[i][j]=a[i][j]+s[i-1][j]+s[i][j-1]-s[i-1][j-1];
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            ans[i][j]=s[i][j]+ans[i-1][j]+ans[i][j-1]-ans[i-1][j-1];
        }
    }
    while(q--){
        int x1,y1,x2,y2;
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
        printf("%lld\n",ans[x2][y2]-ans[x1-1][y2]-ans[x2][y1-1]+ans[x1-1][y1-1]);
    } 
    return 0;
} 

 

posted @ 2020-12-22 23:13  哎呦哎(iui)  阅读(82)  评论(0编辑  收藏  举报