题面
题目描述
Uthuso 的核反应失控了,她在地灵殿释放了几颗大核弹.地灵殿可以看做一个大小为n
∗
*
∗m 的矩阵.一颗大小为k 的核弹,对于任意一个与爆炸中心曼哈顿距离小于k 的地区,会造成(k-(该地区到爆炸中心曼哈顿距离))
∗
*
∗(该地区的价值)的损失.
现在,地灵殿方面想统计一下每颗核弹造成的损失,请你来帮忙计算.
输入
从flare.in 中读入数据第一行为两个整数n,m
接下来n 行每行m 个整数,代表第i 行第j 个区域的价值
接下来一行为一个整数Q,代表核弹的数目.
接下来Q 行每行三个整数x,y,k,代表第i 颗核弹的爆炸中心以及它的大小.
输出
输出到文件flare.out 中Q 行,每行1 个整数,代表第i 颗核弹的损失.
样例输入
5 5
1 2 3 4 5
9 8 7 6 5
2 3 3 3 3
6 6 6 6 6
1 4 2 8 5
5
1 1 1
5 5 1
3 3 3
2 2 2
4 2 2
样例输出
1
5
83
37
31
数据范围
对于30%的数据,满足n<=300,m<=300,Q<=300
对于60%的数据,满足n<=300,m<=300
对于100%的数据,满足
1<=n<=2000,
1<=m<=2000,
1<=Q<=200000,
1<=k<=min(x,y,n-x+1,m-y+1),
1<=每个区域的价值<=1000000
题解
这题的想法其实很简单,只要把原图旋转四十五度就可以正常的求和了,但若要 O ( 1 ) O(1) O(1)实现,稍微推一下,把前缀和展开,就能得到类似于一个X行的东西,只要对旋转后的前缀和再求一遍前缀和就行了。
代码
不知道为什么会被卡常,大吸了一口氧才过去
#include<bits/stdc++.h>
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
using namespace std;
#define x(i,j) x[i]-j+1
#define y(i,j) y[i]+j-1
int i,j,n,m,k,l,o,p,x[2005],y[2005];
long long b[4005][4005],qzh[4005][4005],zs[4005][4005],ys[4005][4005];
inline int read() {
int x=0,f=0;char c=getchar();
while (c<'0'||c>'9') f=(c=='-')?1:f,c=getchar();
while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return f?-x:x;
}
inline void write(long long a)
{
if(a>9)
write(a/10);
putchar(a%10+'0');
}
int main()
{
freopen("flare.in", "r", stdin);
freopen("flare.out", "w", stdout);
n=read();m=read();
x[0]=m-1;
y[0]=0;
for (register int i=1;i<=n;++i)
{
x[i]=x[i-1]+1;
y[i]=y[i-1]+1;
}
for (register int i=1;i<=n;++i)
{
for (j=1;j<=m;j++) {o=read(); b[x(i,j)][y(i,j)]=o;}
}
n=n+m-1;
for (register int i=1;i<=n;++i)
{
for (register int j=1;j<=n;++j)
{
qzh[i][j]=qzh[i-1][j]+qzh[i][j-1]-qzh[i-1][j-1]+b[i][j];
zs[i][j]=zs[i-1][j-1]+qzh[i][j];
ys[i][j]=ys[i-1][j+1]+qzh[i][j];
}
}
int q;
scanf("%d",&q);
while (q--)
{
int x2,y2;
long long sum=0;
x2=read();y2=read();k=read();
int xx=x(x2,y2),yy=y(x2,y2);
int xx2=xx+k-1,yy2=yy-k;
yy=yy+k-1,xx=xx2;
sum=(zs[xx][yy]-zs[xx-2*k][yy-2*k])-(ys[xx2][yy2]-ys[xx2-2*k][yy2+2*k]);
write(sum);putchar('\n');
}
}