题目
有n(n<=1e5)颗星星,有一个星星的最大亮度c(1<=c<=10),
星星每秒的亮度会+1,达到c后,下一秒会清零然后再加
第i颗星星位于(xi,yi)(1<=xi<=100,1<=yi<=100)的位置
每颗星星有一个初始亮度si(0<=si<=c)
有q(q<=1e5)次询问,第j次询问在tj(0<=tj<=1e9)时,
某个给定的矩形(给出左下角坐标和右上角坐标)内,
所有星星当前的亮度之和是多少
思路来源
https://blog.csdn.net/weixin_36571742/article/details/76522026
题解
开一个dp数组dp[105][105][10],
dp[x][y][t]代表(x,y)及其左下角区域,在第0秒时,亮度为t的点的数量
然后其在T秒之后,亮度应为(t+T)%(c+1),数量是不变的,变的只是贡献
所以统计数量用dp的二维前缀和,然后增序处理询问即可
自己在做的时候,忽略了这个第三维,导致一直想着如何动态更新,GG
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1e5+10;
int dp[105][105][15];//点(i,j)及左下角部分,亮度为k的点的数量
int num[105][105][15];
int n,q,c;
int x,y,s;
int t,x1,y1,x2,y2;
int ans;
int main()
{
scanf("%d%d%d",&n,&q,&c);
for(int i=1;i<=n;++i)
{
scanf("%d%d%d",&x,&y,&s);
num[x][y][s]++;
}
for(int i=0;i<=c;++i)
{
for(int x=1;x<=100;++x)
{
for(int y=1;y<=100;++y)
dp[x][y][i]=dp[x-1][y][i]+dp[x][y-1][i]-dp[x-1][y-1][i]+num[x][y][i];
}
}
for(int i=1;i<=q;++i)
{
scanf("%d%d%d%d%d",&t,&x1,&y1,&x2,&y2);
ans=0;
for(int j=0;j<=c;++j)
{
int now=(t+j)%(c+1);//亮度为j实际变成亮度为t
int num=dp[x2][y2][j]-dp[x1-1][y2][j]-dp[x2][y1-1][j]+dp[x1-1][y1-1][j];
ans+=now*num;
}
printf("%d\n",ans);
}
return 0;
}