题目
分析
这题与P2367:语文成绩很相似,也要用到差分和前缀和,但这次是在一个矩阵中进行。
其核心公式是:
- 差分公式:\(diff[i][j]=a[x][y]-a[x-1][y]-a[x][y-1]+a[x-1][y-1]\)。
- 前缀和公式:\(a[i][j]=\sum_{i=1}^{x}\sum_{j=1}^{y}diff[i][j]\)。
参照一维的情形,要修改\([x, y]\)之间的值的时候,我们是将diff[x]+=z, diff[y+1]-=z
。而求部分和的时候,是diff[y]+=diff[x-1]
。(参见P2367:语文成绩中的代码。)
扩展到二维时,从\([x-1][y-1]\)扩展到\([x][y]\)时,需要有两个方向的扩展:\(x-1\to x, y-1\to y\),但这么一来\([x, y]\)计算了两次,所以最终要调整一次。
因此,差分公式需要调整:
diff[x1, y1]++; //起始点增加
diff[x2+1][y1]-- //纵向终点调整
diff[x1][y2+1]-- //横向终点调整
diff[x2+1][y2+1]++ //最终调整
所以,最终的前缀和公式就变成:a[i][j]=a[i][j]+a[i-1][j]+a[i][j-1]-a[i-1][j-1]
。
答案
思考
特别注意:代码中向量的大小都调整到了size+2
,设定为size+1
会出现越界,因为我们在代码中要操作到size+1
的位置:
for(int i=1;i<=carpets_count;i++)
{
int x1, y1, x2, y2;
cin>>x1>>y1>>x2>>y2;
ranges[x1][y1]++;
ranges[x1][y2+1]--;
ranges[x2+1][y1]--;
ranges[x2+1][y2+1]++;
}