2019 ACM-ICPC 上海网络赛 B. Light bulbs (差分)

Posted wulitaotao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2019 ACM-ICPC 上海网络赛 B. Light bulbs (差分)相关的知识,希望对你有一定的参考价值。

题目链接:Light bulbs
比赛链接:The Preliminary Contest for ICPC Asia Shanghai 2019

题意

给定 (N) 个灯泡 (编号从 (0)(N - 1)),初始都是关闭的。

给定 (M) 个操作,每个操作包含 (L)(R),对 ([L, R]) 内的所有灯泡改变状态。

求最后有几个灯泡是亮的。

思路

题目挺简单的,翻转奇数次的灯泡是亮的,所以要求每个灯泡翻转的次数。

容易想到可以用差分。

对所有操作的两个端点排序,求差分数组 (d[])

然后根据差分数组求前缀和,差分数组相邻两个数 (d[l])(d[r]) 所在的区间 ([l, r)) 内的每个数都加上 (d[l]),那么如果 (d[l]) 为奇数,(ans += (r - l))。时间复杂度 (O(MlogM))

于是就有了下面的代码。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 10;

int pos[2010];

int main() {
    int T;
    scanf("%d", &T);
    int kase = 0;
    while(T--) {
        int n, m;
        scanf("%d%d", &n, &m);
        vector<int> d(n + 10);
        memset(pos, 0, sizeof(pos));
        unordered_map<int, int> mp;
        int cnt = 0;
        for(int i = 1; i <= m; ++i) {
            int l, r;
            scanf("%d%d", &l, &r);
            ++d[l];
            --d[r + 1];
            if(mp[l] == 0) {
                pos[cnt++] = l;
                mp[l] = 1;
            }
            if(mp[r + 1] == 0) {
                pos[cnt++] = r + 1;
                mp[r + 1] = 1;
            }
        }
        sort(pos, pos + cnt);
        ll ans = 0;
        for(int i = 1; i < cnt; ++i) {
            if(d[pos[i - 1]] & 1) ans += pos[i] - pos[i - 1];
            d[pos[i]] = d[pos[i - 1]] + d[pos[i]];
        }
        if(d[pos[cnt - 1]] & 1) ans += n - pos[cnt - 1];
        printf("Case #%d: %lld
", ++kase, ans);
    }
    return 0;
}

然后就 TLE 了。这题时间和空间卡的很紧。

AC 代码

用 map 存差分数组,还自动排序了。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 10;

int main() {
    int T;
    scanf("%d", &T);
    int kase = 0;
    while(T--) {
        int n, m;
        scanf("%d%d", &n, &m);
        map<int, int> d;
        int cnt = 0;
        for(int i = 1; i <= m; ++i) {
            int l, r;
            scanf("%d%d", &l, &r);
            ++d[l];
            --d[r + 1];
        }
        ll ans = 0;
        auto it = d.begin();
        int p = it->first;
        int v = it->second;
        ++it;
        for(; it != d.end(); ++it) {
            if(v & 1) ans += it->first - p;
            it->second = v + it->second;
            p = it->first;
            v = it->second;
        }
        if(v & 1) ans += n - p;
        printf("Case #%d: %lld
", ++kase, ans);
    }
    return 0;
}

以上是关于2019 ACM-ICPC 上海网络赛 B. Light bulbs (差分)的主要内容,如果未能解决你的问题,请参考以下文章

2017 ACM-ICPC 亚洲区(西安赛区)网络赛: B. Coin 概率题

2019ACM-ICPC南京网络赛Holy Grail (SPFA模板题)

ACM-ICPC 2019南昌网络赛I题 Yukino With Subinterval

2019-ACM-ICPC-南京区网络赛-D. Robots-DAG图上概率动态规划

2019ACM-ICPC沈阳网络赛-C-Dawn-K's water(完全背包模板题)

2019ACM-ICPC沈阳网络赛-K-Guanguan's Happy water(思维+暴力)