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;
}