LG8470

题意

\(n\) 次操作,每次在矩形地面上选择一个格子 \((x_i,y_i)\),在上面加上 \(z_i\) 个方块。一个立体图形的「侧面积」定义为所有方块的前后左右面不紧贴着另一个方块,则该面计入「侧面积」。求每次操作后立体图形的侧面积。

分析

最直接的想法就是每加入 \(z_i\) 个方块后,总的侧面积直接加上 \(z_i \times 4\) 即可(前后左右共四个面)。但是,如果它的四周也有方块,那么这样就是不完整的,因此我们要分类讨论。我们不妨先设 \((x_i,y_i)\) 上原有 \(a\) 个方块,周围的其中一个位置有 \(b\) 个方块(其它位置同理),现要在 \((x_i,y_i)\) 的位置加入 \(c\) 个方块。

  • \(a \le b\)\(a+c \le b\)

这种情况是原来比周围的低,增加了方块之后仍然比周围的低。增加了 \(c\) 个方块后,那么两者紧贴的面积就增加了 \(c\),即侧面积减少了 \(c\)

  • \(a \le b\)\(a+c >b\)

这种情况是原来比周围的低,但加了 \(c\) 个方块后,超过了周围的高度。因此很容易得知原来的高度差 \(b-a\) 没了,然后产生了新的高度差 \((a+c)-b\),因此此时的侧面积要加上 \((a+c)-b-(b-a)\)

  • \(a > b\)

这种情况不用多说了,原来已经比周围的高,那么加上 \(c\) 个方块后也不会有方块紧贴着,所以侧面积直接加上 \(c\) 即可。

实现

由于 \(1 \le x,y \le 10^9\),普通的二维数组无法开到这么大的值域,因此我们可以用 map,map 里再开一个 map,就可以达到二维数组的效果(或者用 hash 也可以)。注意,求侧面积的变量要开 unsigned long long(极限数据 \(3 \times 10^5 \times 10^{13} \times4 = 1.2 \times 10^{19}\),会爆 long long)。

具体实现细节见代码:

#include <bits/stdc++.h>
using namespace std;
unsigned long long ans;
long long z;
int x,y;
map<int,map<int,long long> > a;
int main()
{
	int n;
	cin>>n;
	while(n--)
	{
		cin>>x>>y>>z;
		a[x][y]+=z;
		if(a[x-1][y]>=a[x][y]) ans=ans-z;
		else if(a[x][y]-z<a[x-1][y]) ans=ans-(a[x-1][y]-(a[x][y]-z))+(a[x][y]-a[x-1][y]);
		else ans=ans+z;
		if(a[x+1][y]>=a[x][y]) ans=ans-z;
		else if(a[x][y]-z<a[x+1][y]) ans=ans-(a[x+1][y]-(a[x][y]-z))+(a[x][y]-a[x+1][y]);
		else ans=ans+z;
		if(a[x][y-1]>=a[x][y]) ans=ans-z;
		else if(a[x][y]-z<a[x][y-1]) ans=ans-(a[x][y-1]-(a[x][y]-z))+(a[x][y]-a[x][y-1]);
		else ans=ans+z;
		if(a[x][y+1]>=a[x][y]) ans=ans-z;
		else if(a[x][y]-z<a[x][y+1]) ans=ans-(a[x][y+1]-(a[x][y]-z))+(a[x][y]-a[x][y+1]);
		else ans=ans+z;
		cout<<ans<<endl;
	}
}
posted @ 2024-01-20 17:43  liyilang2021  阅读(1)  评论(0编辑  收藏  举报