Codeforces Round #427 (Div. 2) 835C-Star sky 二维前缀和

839C:http://codeforces.com/problemset/problem/835/C

题意:给出星星的个数,最大亮度(每时间+1,亮度+1,但不超过最大亮度),观测者观测的次数及时刻, 求观测时刻矩形内星星的亮度和。

这里要用到一个三维数组,一维记录时间,另外两维记录时间t时坐标(x,y)处的亮度。

星星某时刻的亮度处理:0时刻为s,此后每时间+1,亮度+1,每超过最大亮度c,亮度变为0,如此循环下去,也就是说,时刻t的亮度为(s+t)%(c+1);

矩阵和:

二维前缀和预处理: 一维的前缀和:sum[i]=sum[i-1]+a[i];

                       二维可以先将每一列求和,再行求和:

     for (int t = 0; t < c; t++)
        {
            for (int i = 1; i <= 100; i++)
                for (int j = 1; j <= 100; j++)
                    dp[i][j][t] += dp[i][j - 1][t];
            for (int j = 1; j <= 100; j++)
                for (int i = 1; i <= 100; i++)
                    dp[i][j][t] += dp[i - 1][j][t];
        }

  此外还可以找递推关系:dp[i][j]+=dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1];

那么任意子矩阵的和可以由矩阵(0,0)-(x2,y2)减去矩阵(0,0)-(x1-1,y2)和(0,0)-(x2,y1-1)再加上(0,0)-(x1-1,y1-1)得到  ((,)-(,)为矩阵左上和右下角坐标)

然后将上面的处理凑到一起就好了o(* ̄▽ ̄*)o

#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
int dp[105][105][15];
int n, q, c;
int main()
{
    cin >> n >> q >> c;
        c++;
        for (int i = 1; i <= n; i++)
        {
            int x, y, s; 
            cin >> x >> y >> s;
            for (int t = 0; t < c; t++)
            {
                dp[x][y][t] += (s+t) % c;
            }
        }
        for (int t = 0; t < c; t++)
        {
            for (int i = 1; i <= 100; i++)
                for (int j = 1; j <= 100; j++)
                    dp[i][j][t] += dp[i][j - 1][t];
            for (int j = 1; j <= 100; j++)
                for (int i = 1; i <= 100; i++)
                    dp[i][j][t] += dp[i - 1][j][t];
        }
        while (q--)
        {
            int t, x1, y1, x2, y2;
            cin >> t >> x1 >> y1 >> x2>> y2;
            t %= c;
            int ans = 0;
            ans += dp[x2][y2][t]- (dp[x1 - 1][y2][t] + dp[x2][y1 - 1][t])+ dp[x1 - 1][y1 - 1][t];
            cout << ans << endl;
        }
    return 0;
}

 

posted @ 2017-08-28 14:23  #Egoist#  阅读(161)  评论(0编辑  收藏  举报