题目描述
小 Q 新学会了一种魔法,可以对一个 N行M列 的网格上的敌人造成伤害
第 i 次使用魔法可以对网格上的一个十字形区域(即第 xi 行和第 yi 列的并)中的每个格子上的敌人造成 zi 点伤害
现在小 Q 一共使用了 H 次魔法,你需要在所有的施法完成之后统计造成伤害的情况,详见输出描述
提醒:本题输入规模较大,请使用高效的输入方式
1
≤
H
≤
500
,
000
;
1
≤
x
i
,
y
i
,
z
i
,
N
,
M
≤
2000
;
1
≤
x
i
≤
N
;
1
≤
y
i
≤
M
1≤H≤500,000;\ \ 1≤xi,yi,zi,N,M≤2000 ;\ \ 1≤xi≤N;\ \ 1≤yi≤M
1≤H≤500,000; 1≤xi,yi,zi,N,M≤2000; 1≤xi≤N; 1≤yi≤M
输入描述:
第一行 3 个数字 N,M,H
接下来 H 行,每行 3 个正整数 xi,yi,zi
输出描述:
为了避免大量的输出,假设第 i 行第 j 列受到的总伤害是
w
i
j
w_{ij}
wij
你只需要输出
Σ
w
i
j
(
i
+
j
)
Σw_{ij}(i+j)
Σwij(i+j)对
1
0
9
+
7
10^9+7
109+7 取模的结果即可
输入
5 5 5
1 1 1
2 2 2
3 3 3
4 4 4
5 5 5
输出
890
说明
造成伤害的情况是:
1 3 4 5 6
3 2 5 6 7
4 5 3 7 8
5 6 7 4 9
6 7 8 9 5
补充的说明:
890 = 1*(1+1)+3*(1+2)+4*(1+3)+…+5*(5+5),一共25项累加得到890
题解
- 数据范围很大,我们需要加速过程
- 考虑如图
- 假设在 ( x = 3 , y = 2 ) (x=3,y=2) (x=3,y=2) 位置 添加 Δ \Delta Δ
- 那么我们来思考它的贡献,只有 x = 3 x=3 x=3 的行, y = 2 y=2 y=2 的列有 Δ \Delta Δ 的贡献。值就是图中写的
- 那么我们可以总结一下规律,就可以在 O ( H ) O(H) O(H) 复杂度内解决问题
AC-Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9+7;
const int maxn = 2e3+7;
int main(){
ll N, M, H; while(scanf("%lld%lld%lld", &N, &M, &H) == 3) {
ll n = (1+N)*N/2; // 1+...+N
ll m = (1+M)*M/2;
ll ans = 0;
for(int i = 0; i < H; ++i) {
ll x, y, z; scanf("%lld%lld%lld", &x, &y, &z);
ans = (ans + z * (n + m + (N-1)*y % mod + (M-1)*x % mod) % mod) % mod;
}
printf("%lld\n", ans);
}
return 0;
}