C. Star sky(Codeforces Round #427 (Div. 2) C)

题目大意:给在100*100的网格上,有n颗星星, 每颗星星有自己的亮度,最大亮度是c,每过t秒,星星的亮度就会加t,如果亮度超过了c,就会变成0,然后继续从0开始增加。现在有q次查询, 每次查询会输入一个时间t,和两个点,要求输出,在t时间下,这两个点所组成的矩形中星星亮度的和。
题目思路:首先我们现将输入的查询全部存起来,输入的时候将每个查询的t对(c+1) 取模, 然后对t进行排序。然后我们对查询中的t从小到大进行处理,t的值一共最多也就c+1种(c<= 10)。对于每个t, 我们先打出这样一个网格map[100][100], map[i][j]的意思是在坐标i, j 这个点上星星的亮度值,每颗星星的亮度加上t后要对(c+1)取模,同一个点上可能有两颗星星,亮度直接相加就可以了。然后求出对于每个i来说, j的前缀和。也就是说现在map[i][j] 表示的是当x == i时, 对于y轴前j位置的亮度和是多少(这个可以理解为一个线段的贡献值)。 然后对于每个查询来说我们只需要,将map[x1][y2] + map[x1+1][y2] + ……+map[x2][y2] - (map[x1][y1-1] + map[x1+1][y1-1] + ……+map[x2][y1-1] )这个就是查询的答案了,这样一共处理c次
复杂度在o(cn) + o(q*100) + o(10000) 完全可以接受。
代码如下:

#include <iostream>
#include <stdio.h>
#include <cstring>
#include <algorithm>
using namespace std;
#define Max_N 100000+100
int x[Max_N], y[Max_N], s[Max_N];
int map1[110][110];
int n, q, c;
struct point{
    int x1, y1;
    int x2, y2;
    int t;
    int num;
};
point que[Max_N];
bool cmp(const point &a, const point &b)
{
    return a.t < b.t;
}
int b[110][110];
int ans[Max_N];
int main()
{ 
    cin >> n >> q >> c;
    for (int i = 1; i <= n; i++) {
        scanf("%d%d%d", &x[i], &y[i], &s[i]);
    }
    for (int i = 0; i < q; i ++) {
        scanf("%d%d%d%d%d", &que[i].t, &que[i].x1, &que[i].y1, &que[i].x2, &que[i].y2);
        que[i].t %= (c+1);
        que[i].num = i;
    }
    sort (que, que + q, cmp);
    //cout << que[0].t << endl;
    int l = 0;
    memset(ans, 0, sizeof(ans));
    for (int i = 0; i <= c; i++) {
        memset(map1, 0, sizeof(map1));
        memset(b, 0, sizeof(b));
        for (int j = 1; j <= n; j++) {
            map1[x[j]][y[j]] += (s[j] + i) % (c+1);
        }
        for (int j = 1; j <= 100; j++) {
            for (int w = 1; w <= 100; w++) {
                map1[j][w] += map1[j][w-1];
            }
        }
        for (; l < q; l++) {
            if (que[l].t != i) break;
            int _x1 = que[l].x1;
            int _y1 = que[l].y1;
            int _x2 = que[l].x2;
            int _y2 = que[l].y2;
            int w = que[l].num;
            int ans1 = 0;
            int ans2 = 0;
            for (int ss = _x1; ss <= _x2; ss++) {
                ans1 += map1[ss][_y1-1];
                ans2 += map1[ss][_y2];
            }
            ans[w] = ans2 - ans1;
        }
    }
    for (int i = 0; i < q; i++)
        cout << ans[i] << endl;

    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值