题意:天上有很多星星,每个星星有他自己的坐标和初始亮度
每个星星的亮度在一秒内会加一如果大于最大亮度C就会变为0
观察星星,给出视野范围(矩形)的左下角和右上角,以及观察的时间
问视野中星星亮度总和是多少
思路:一开始看到这道题,二维区间,想到了线段树....(不要问我为什么想到这个
我们知道星星的亮度是在发生变化的,所以我们需要一个时间t去记录星星亮度的状态
同时利用二维前缀和的性质求矩形区间的和。同时由于不需要更新数组所以直接预处理前缀和
用sum[i][j][k] 表示左下角 (0,0)到右上角(i,j)统计亮度为k的星星的个数
由容斥可以得到(或者差分性质) sum[i][j][k] = sum[i-1][j][k] +sum[i][j-1][k] -sum[i-1][j-1][k];
(是不是有点像dp..) 在询问的时候我们就遍历所问区间中从1~c的所有亮度的总和,对其求和即为答案
完整代码:
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> using namespace std; const int maxn = 105; int n,m,c; int sum[maxn][maxn][15]; void init(){ for(int i = 1; i <= 100; i++){ for(int j = 1; j <= 100; j++){ for(int k = 0; k <= c; k++){ sum[i][j][k] += sum[i-1][j][k] + sum[i][j-1][k] - sum[i-1][j-1][k]; } } } } int main(){ while(cin>>n>>m>>c){ memset(sum,0,sizeof(sum)); for(int i = 0;i<n;i++){ int x,y,z; cin>>x>>y>>z; sum[x][y][z]++; } init(); for(int i = 0;i<m;i++){ int t,x1,x2,y1,y2; int ans = 0; cin>>t>>x1>>y1>>x2>>y2; for(int k = 0;k<=c;k++){ //注意边界 int num = sum[x2][y2][k]-sum[x1-1][y2][k]-sum[x2][y1-1][k]+sum[x1-1][y1-1][k]; ans += ((k+t)%(c+1))*num; } cout<<ans<<endl; } } }