_YueYang

导航

洛谷P5542题解

题目链接:https://www.luogu.com.cn/problem/P5542

对于这道题,我们首先要知道前缀和的概念,比如下图:

定义Si,j为上图橙色部分的总和。

如上图,这题需要快速将(x1,y1),(x2,y2)中的数全部加一。

根据前缀和的定义,我们在(x1,y1)处加上一(最后再算一遍二维前缀和),它后面的数全部都加上了一,但很多不必要的也加上了一,如下图绿色部分:

于是,我们再(x1,y2+1)处减一,又变成了下图:(PS:洛谷中这道题是点,在这里,我们讨论的是格子,做题中,我们要注意)

再在(x2+1,y1)处减一,又变成了下图:

这时,我们可以看到,由于减了两次,右下角(上图蓝色区域)全部减了一,怎么办呢?再加回来(在(x2+1,y2+1)处)

这时,(x1,y1)至(x2,y2)都加上了一,并且其他没有改变。

总结步骤:

 a[x1][y1]++; a[x1][y2+1]--; a[x2+1][y1]--; a[x2+1][y2+1]++; 

上代码:

 1 #include<cstdio>
 2 using namespace std;
 3 int k,n;
 4 int a[2500][2500];
 5 int x1,y1,x2,y2;
 6 int ans;
 7 int main(){
 8     scanf("%d%d",&n,&k);
 9     for(int i=1;i<=n;++i){
10         scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
11         a[x1+1][y1+1]++;
12         a[x1+1][y2+1]--;
13         a[x2+1][y1+1]--;
14         a[x2+1][y2+1]++;
15     }//为了防止越界,所以都加上了一
16     for(int i=1;i<=1005;++i)
17         for(int j=1;j<=1005;++j){
18             a[i][j]+=a[i-1][j]+a[i][j-1]-a[i-1][j-1];//二维前缀和
19             if(a[i][j]==k)++ans;//统计答案
20         }
21     printf("%d",ans);
22     return 0;
23 }

 

posted on 2020-05-05 20:34  _YueYang  阅读(195)  评论(0编辑  收藏  举报