4.19 每日一题题解

牛妹吃豆子

涉及知识点:

  • 二维前缀和/差分

solution:

  • (大家周末愉快,昨天学习了二分,今天要不学一下差分QAQ)
  • (为了便于大家理解,我们先复习(没学过的就当学习)一下一维前缀和和差分:)
  • (给你一串长度为n的数列a1,a2,a3......an,要求对[L,R]进行多次操作:)
  • (m次操作1:将[L,R]内的元素都加1)
  • $k次操作2:询问[L,R]内的元素和 $
  • (操作1,方法就是a[L] += 1, a[R+1] -= 1,记录差分)
  • (原理很简单,因为我们只对[L,R]区间进行加1,[R+1,n] 这个区间里的数没必要加1,所以需要减掉P)
  • (操作2,先记录差分数组,[L-R]的和就等于前缀和a[R] - a[L-1])

std:

#include <bits/stdc++.h>
using namespace std;
#define ll long long 
const int maxn = 1e5 + 5;
int a[maxn];

int main(){
    int n,m,k,L,R,P;
    cin>>n>>m>>k;
    while(m--){
        cin>>L>>R;
        a[L]++;
        a[R+1]--;
    }
    for(int i=1;i<=n;i++){
        a[i] += a[i-1];
    }
    for(int i=1;i<=n;i++){
        a[i] += a[i-1];
    }
    while(k--){
        cin>>L>>R;
        cout<<a[R] - a[L-1]<<endl;
    }
    return 0;
}
  • (了解了一维数组前缀和以及差分,那么这道题就是二维数组前缀和以及差分)
  • (希望大家能通过明白一维数组来类比推理二维数组前缀和以及差分的原理)

std:

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 2005;
ll a[maxn][maxn];
 
int main(){
    int n,m,k,q,x1,x2,y1,y2;
    scanf("%d%d%d%d",&n,&m,&k,&q);
    while(k--){
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
        a[x1][y1]++;
        a[x2+1][y2+1]++;
        a[x1][y2+1]--;
        a[x2+1][y1]--;
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            a[i][j] = a[i-1][j] + a[i][j-1] - a[i-1][j-1] + a[i][j];
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            a[i][j] = a[i-1][j] + a[i][j-1] - a[i-1][j-1] + a[i][j];
        }
    }
    while(q--){
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
        printf("%lld
",a[x2][y2] - a[x2][y1-1] - a[x1-1][y2] + a[x1-1][y1-1]);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/QFNU-ACM/p/12730734.html