题目大意:给你个100*100的棋盘,有些点上有点权,会随时间改变。设点权为x(x<=10),则在时间t他的点权为 (t+x)%(c+1) 。每次询问给你时间t,和一个矩阵范围(x1,y1,x2,y2),问你矩阵覆盖区域内的点权和是多少。因为棋盘范围很小,权值种类也很少,所以我们预处理一个数组cnt[k][x][y],表示(1,1,x,y)矩阵内点权为k的点的个数。用容斥原理处理就好了。。 O(c∗1002) 然后对于每次询问,答案即为 ∑k=0c(k+t)%(c+1)∗num[k][x1][y1][x2][y2] .num数组表示(x1,y1,x2,y2)矩阵范围内点权为k的点的个数,由cnt数组利用容斥原理可以 O(1) 的得到。所以每次询问可以在 O(c) 的时间内得到。
#include <cstdio>
#include <cstring>
#define N 105
int n,q,c,cnt[11][N][N];
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*f;
}
int main(){
// freopen("a.in","r",stdin);
n=read();q=read();c=read();
for(int i=1;i<=n;++i){
int x=read(),y=read(),s=read();
cnt[s][x][y]++;
}
for(int x=1;x<=100;++x)
for(int y=1;y<=100;++y)
for(int k=0;k<=c;++k)
cnt[k][x][y]+=cnt[k][x-1][y]+cnt[k][x][y-1]-cnt[k][x-1][y-1];
while(q--){
int t=read(),x1=read(),y1=read(),x2=read(),y2=read(),ans=0;
for(int k=0;k<=c;++k){
ans+=(k+t)%(c+1)*(cnt[k][x2][y2]-cnt[k][x1-1][y2]-cnt[k][x2][y1-1]+cnt[k][x1-1][y1-1]);
}
printf("%d\n",ans);
}
return 0;
}