NC21125 践踏

题目链接

题目

题目描述

首先给定一个定值k,支持如下操作(在数轴上)

  1. 加入一条线段[l,r]
  2. 删除一条已经存在的线段
  3. 给定x,问有多少个区间包含x+kt,其中t是一个整数变量,即t ∈ Z

比如说当x=2,k=3的时候,区间[7,10]是应该算入答案的,因为x+2k=8,且7 ≤ 8 ≤ 10

如果n=0,那么你只需要输出一行"fafa"然后结束程序即可(注意不输出双引号)

输入描述

第一行两个整数n,k,分别表示操作次数以及定值k
之后有n行,每行先输入一个整数op,之后分类讨论:

  1. op=1,此时再输入[l,r],表示加入一个区间[l,r]
  2. op=2,此时再输入[l,r],表示删除区间[l,r],保证这个区间存在(如果存在多个相同的区间,那么只需要删除其中的任意一个)
  3. op=3,此时再输入x,之后需要输出答案并换行

输出描述

对于每一个op=3的操作,输出查询结果后换行

示例1

输入

10 7
1 3393 14151
3 13229
1 3427 18356
1 7602 20138
1 8566 28714
1 1076 32552
2 3427 18356
2 8566 28714
3 10962
1 387 7783

输出

1
3

说明

(以下内容与本题无关)
这个样例,无疑是善良的出题人无私的馈赠。
大量精心构造的 n ≤ 100 的测试数据,涵盖了测试点中所有出现性质的组合。
你可以利用这个测试点,对自己的程序进行全面的检查。
足量的数据组数、不大的数据范围和多种多样的数据类型,能让程序中的错误无处遁形。
出题人相信,这个美妙的样例,可以给拼搏于 AC 这道题的逐梦之路上的你,提供一个有力的援助。

示例2

输入

0 0

输出

fafa

备注

一共有20个测试点,每个测试点5分
有4个测试点保证:\(n≤1000\)
有另外5个测试点保证:\(n≤10000\)
对于全部数据,保证:
\(0 ≤ n,k ≤ 10^5\)\(0 ≤ l ≤ r ≤ 10^9\)\(0 ≤ x ≤ 10^9\)

题解

知识点:树状数组,离散化,数论。

\(n = 0\) 时,输出 fafa

  1. \(k = 0\) 时,需要区间修改、单点询问,可以用树状数组维护,需要先离散化区间端点。
  2. \(k \neq 0\) 时,需要区间修改、固定间隔的多点询问,注意到间隔是固定的,因此区间覆盖可以在模 \(k\) 意义下计算贡献,但要注意端点顺序可能相反,要分类处理,可以用树状数组维护。

时间复杂度 \(O(n\log n)\)

空间复杂度 \(O(n)\)

代码

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

template<class T>
struct Discretization {
    vector<T> uniq;
    Discretization() {}
    Discretization(const vector<T> &src) { init(src); }
    void init(const vector<T> &src) {
        uniq = src;
        sort(uniq.begin() + 1, uniq.end());
        uniq.erase(unique(uniq.begin() + 1, uniq.end()), uniq.end());
    }
    int get(T x) { return lower_bound(uniq.begin() + 1, uniq.end(), x) - uniq.begin(); }
};

struct Query {
    int op;
    int x, l, r;
};

struct T {
    ll sum;
    static T e() { return { 0 }; }
    T &operator+=(const T &x) { return sum += x.sum, *this; }
};
template<class T>
class Fenwick {
    int n;
    vector<T> node;

public:
    Fenwick(int _n = 0) { init(_n); }

    void init(int _n) {
        n = _n;
        node.assign(n + 1, T::e());
    }

    void update(int x, T val) { for (int i = x;i <= n;i += i & -i) node[i] += val; }

    T query(int x) {
        T ans = T::e();
        for (int i = x;i >= 1;i -= i & -i) ans += node[i];
        return ans;
    }
};

int main() {
    std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int n, k;
    cin >> n >> k;
    if (n == 0) return cout << "fafa" << '\n', 0;
    if (k == 0) {
        vector<Query> q(n + 1);
        vector<int> src(1);
        for (int i = 1;i <= n;i++) {
            int op;
            cin >> op;
            if (op == 1 || op == 2) {
                int l, r;
                cin >> l >> r;
                l++, r++;
                q[i] = { op,-1,l,r };
                src.push_back(l);
                src.push_back(r);
            }
            else {
                int x;
                cin >> x;
                x++;
                q[i] = { op,x,-1,-1 };
                src.push_back(x);
            }
        }
        Discretization<int> dc(src);
        Fenwick<T> fw(dc.uniq.size());
        for (int i = 1;i <= n;i++) {
            auto [op, x, l, r] = q[i];
            if (op == 1) fw.update(dc.get(l), { 1 }), fw.update(dc.get(r) + 1, { -1 });
            else if (op == 2) fw.update(dc.get(l), { -1 }), fw.update(dc.get(r) + 1, { 1 });
            else cout << fw.query(dc.get(x)).sum << '\n';
        }
    }
    else {
        Fenwick<T> fw(k + 1);
        for (int i = 1;i <= n;i++) {
            int op;
            cin >> op;
            if (op == 1) {
                int l, r;
                cin >> l >> r;
                if (r - l + 1 >= k) fw.update(1, { 1 }), fw.update(k + 1, { -1 });
                else {
                    l %= k;
                    r %= k;
                    l++, r++;
                    if (l <= r) fw.update(l, { 1 }), fw.update(r + 1, { -1 });
                    else fw.update(l, { 1 }), fw.update(k + 1, { -1 }), fw.update(1, { 1 }), fw.update(r + 1, { -1 });
                }
            }
            else if (op == 2) {
                int l, r;
                cin >> l >> r;
                if (r - l + 1 >= k) fw.update(1, { -1 }), fw.update(k + 1, { 1 });
                else {
                    l %= k;
                    r %= k;
                    l++, r++;
                    if (l <= r) fw.update(l, { -1 }), fw.update(r + 1, { 1 });
                    else fw.update(l, { -1 }), fw.update(k + 1, { 1 }), fw.update(1, { -1 }), fw.update(r + 1, { 1 });
                }
            }
            else {
                int x;
                cin >> x;
                x %= k;
                x++;
                cout << fw.query(x).sum << '\n';
            }
        }
    }
    return 0;
}
posted @ 2023-04-26 23:59  空白菌  阅读(53)  评论(0编辑  收藏  举报