P8470 [Aya Round 1 E] 乙(two)

题目链接

Solution

本题是动态询问我们图形的侧面积,由于数据较大,肯定不能每一次暴力查找。所以我们考虑每一次的贡献。

假设说我们每一次都没有跟别的方块有冲突,那么每一次的贡献就是 \(z\times 4\),然后我们要考虑重合的部分。

设放的当前方块原来有 \(now\) 个,现在放上去 \(z\) 个,开一个 map,看它前后左右是否有方块,如果有,设它的高度为 \(h\),若 \(h\le now\),则不会有冲突;若 \(h>now\),则出现冲突的高度为 \(\min(z,h-now)\),并且它会影响两个面,所以冲突的面积为 \(2\times \min(z,h-now)\)

所以我们每次查询先加上 \(z\times 4\),再减去冲突的面积就是答案。

注意由于最大的答案可能到 \(1.2\times 10^{19}\),要开 unsigned long long。

Code

#include<bits/stdc++.h>
#define int unsigned long long
using namespace std;
void read(int &x)
{
	char ch=getchar();
	int r=0,w=1;
	while(!isdigit(ch))w=ch=='-'?-1:1,ch=getchar();
	while(isdigit(ch))r=(r<<3)+(r<<1)+(ch^48),ch=getchar();
	x=r*w;
}
map<pair<int,int>,int>mp;
void write(int x)
{
	char ch[20];
	int len=0;
	if(x<0)putchar('-'),x=-x;
	while(x)
	{
		ch[len++]=(x%10)^48;
		x/=10;
	}
	if(len==0)printf("0");
	while(len--)putchar(ch[len]);
	puts("");
}
main()
{
	int T,sum=0;
	read(T);
	while(T--)
	{
		int x,y,z;
		read(x);read(y);read(z);
		int now=mp[make_pair(x,y)];
		if(mp[make_pair(x+1,y)])
		{
			int k=mp[make_pair(x+1,y)];
			if(k>now)sum-=min(k-now,z)*2;
		}
		if(mp[make_pair(x-1,y)]&&x>0)
		{
			int k=mp[make_pair(x-1,y)];
			if(k>now)sum-=min(k-now,z)*2;
		}
		if(mp[make_pair(x,y+1)])
		{
			int k=mp[make_pair(x,y+1)];
			if(k>now)sum-=min(k-now,z)*2;
		}
		if(mp[make_pair(x,y-1)]&&y>0)
		{
			int k=mp[make_pair(x,y-1)];
			if(k>now)sum-=min(k-now,z)*2;
		}
		sum+=z*4;
		mp[make_pair(x,y)]+=z;
		write(sum);
	}
	return 0;
}
posted @ 2022-08-09 09:13  Epoch_L  阅读(24)  评论(0编辑  收藏  举报