Codeforces 835C

题目链接:http://codeforces.com/problemset/problem/835/C

题意:

在天空上划定一个直角坐标系,有 $n$ 颗星星,每颗星星都有坐标 $(x_i,y_i)$,星星初始亮度为 $s_i$,所有星星的亮度有个上限 $c$。

在时刻 $0$,每颗星星都是初始亮度 $s_i$,然后每过一个单位时间,星星亮度都增加 $1$,如果亮度一旦超过 $c$ 就立刻变为 $0$。

现在有 $q$ 次观察天空的机会,观察时刻为 $t_i$,观察的视野为左下角为 $(x_{1i},y_{1i})$,右上角为 $(x_{2i},y_{2i})$ 的平行于坐标轴的长方形。要求出每次观察时,在视野中的星星的亮度和。

题解:

首先星星亮度是周期变化的,周期长度是 $c+1$,所以我们只需要求出周期内每个时刻星星的亮度。

然后我们再用一个二维前缀和,就能 $O(1)$ 查出每个时刻任意长方形范围的星星亮度和。

注意一点,可能多个星星重叠在一个坐标上。

AC代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
const int C=13;
const int X=105, Y=105;
int n,q,c;
struct Star{
    int x,y,s;
}star[N];
int sum[C][X][Y];
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);

    cin>>n>>q>>c;
    for(int i=1;i<=n;i++) cin>>star[i].x>>star[i].y>>star[i].s;

    memset(sum,0,sizeof(sum));
    for(int t=0;t<=c;t++)
    {
        for(int i=1;i<=n;i++)
            sum[t][star[i].x][star[i].y]+=(star[i].s+t)%(c+1);

        for(int x=1;x<=100;x++)
            for(int y=1;y<=100;y++)
                sum[t][x][y]+=sum[t][x-1][y]+sum[t][x][y-1]-sum[t][x-1][y-1];
    }

    for(int i=1,t,x1,y1,x2,y2;i<=q;i++)
    {
        cin>>t>>x1>>y1>>x2>>y2;
        cout<<sum[t%(c+1)][x2][y2]-sum[t%(c+1)][x2][y1-1]-sum[t%(c+1)][x1-1][y2]+sum[t%(c+1)][x1-1][y1-1]<<"
";
    }
}
原文地址:https://www.cnblogs.com/dilthey/p/10460460.html