Codeforces Round #427 (Div. 2) C.Star sky(二维前缀和/线性dp)

题目

有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;
} 

猜你喜欢

转载自blog.csdn.net/Code92007/article/details/89790574