839C:http://codeforces.com/problemset/problem/835/C
题意:给出星星的个数,最大亮度(每时间+1,亮度+1,但不超过最大亮度),观测者观测的次数及时刻, 求观测时刻矩形内星星的亮度和。
这里要用到一个三维数组,一维记录时间,另外两维记录时间t时坐标(x,y)处的亮度。
星星某时刻的亮度处理:0时刻为s,此后每时间+1,亮度+1,每超过最大亮度c,亮度变为0,如此循环下去,也就是说,时刻t的亮度为(s+t)%(c+1);
矩阵和:
二维前缀和预处理: 一维的前缀和:sum[i]=sum[i-1]+a[i];
二维可以先将每一列求和,再行求和:
for (int t = 0; t < c; t++) { for (int i = 1; i <= 100; i++) for (int j = 1; j <= 100; j++) dp[i][j][t] += dp[i][j - 1][t]; for (int j = 1; j <= 100; j++) for (int i = 1; i <= 100; i++) dp[i][j][t] += dp[i - 1][j][t]; }
此外还可以找递推关系:dp[i][j]+=dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1];
那么任意子矩阵的和可以由矩阵(0,0)-(x2,y2)减去矩阵(0,0)-(x1-1,y2)和(0,0)-(x2,y1-1)再加上(0,0)-(x1-1,y1-1)得到 ((,)-(,)为矩阵左上和右下角坐标)
然后将上面的处理凑到一起就好了o(* ̄▽ ̄*)o
#include<iostream> #include<string.h> #include<algorithm> using namespace std; int dp[105][105][15]; int n, q, c; int main() { cin >> n >> q >> c; c++; for (int i = 1; i <= n; i++) { int x, y, s; cin >> x >> y >> s; for (int t = 0; t < c; t++) { dp[x][y][t] += (s+t) % c; } } for (int t = 0; t < c; t++) { for (int i = 1; i <= 100; i++) for (int j = 1; j <= 100; j++) dp[i][j][t] += dp[i][j - 1][t]; for (int j = 1; j <= 100; j++) for (int i = 1; i <= 100; i++) dp[i][j][t] += dp[i - 1][j][t]; } while (q--) { int t, x1, y1, x2, y2; cin >> t >> x1 >> y1 >> x2>> y2; t %= c; int ans = 0; ans += dp[x2][y2][t]- (dp[x1 - 1][y2][t] + dp[x2][y1 - 1][t])+ dp[x1 - 1][y1 - 1][t]; cout << ans << endl; } return 0; }