调了半天忘了要求两次前缀和了。
先对前缀和数组进行修改,
第一次求前缀和得到的是修改后的原矩阵,再求一次前缀和得到二维前缀和,然后根据容斥定理求区间的二维前缀和即可
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
#include<math.h>
#include<vector>
#define ls (p<<1)
#define rs (p<<1|1)
#define mid (l+r)/2
#define over(i,s,t) for(register long long i=s;i<=t;++i)
#define lver(i,t,s) for(register long long i=t;i>=s;--i)
//#define int __int128
using namespace std;
typedef long long ll;//全用ll可能会MLE或者直接WA,试着改成int看会不会A
const ll N=2005;
const ll INF=1e10+9;
const ll mod=2147483647;
const double EPS=1e-10;//-10次方约等于趋近为0
const double Pi=3.1415926535897;
ll n,m,a[N][N];
void add(ll x_1,ll y_1,ll x_2,ll y_2)
{
a[x_1][y_1]++;
a[x_2+1][y_2+1]++;
a[x_1][y_2+1]--;
a[x_2+1][y_1]--;
}
ll k,q;
ll x_1,x_2,y_1,y_2;
int main()
{
scanf("%lld%lld%lld%lld",&n,&m,&k,&q);
while(k--){
scanf("%lld%lld%lld%lld",&x_1,&y_1,&x_2,&y_2);
add(x_1,y_1,x_2,y_2);
}
over(i,1,n)over(j,1,m)
a[i][j]=a[i-1][j]+a[i][j-1]-a[i-1][j-1]+a[i][j];
over(i,1,n)over(j,1,m)
a[i][j]=a[i-1][j]+a[i][j-1]-a[i-1][j-1]+a[i][j];
while(q--)
{
scanf("%lld%lld%lld%lld",&x_1,&y_1,&x_2,&y_2);
ll ans=a[x_2][y_2]+a[x_1-1][y_1-1]-a[x_1-1][y_2]-a[x_2][y_1-1];
printf("%lld\n",ans);
}
return 0;
}