Hướng giải của Truy Vấn Điểm Thuộc Đoạn


Nhớ rằng hướng dẫn giải này chỉ nên sử dụng khi bế tắc, và tuyệt đối không nên sao chép mã nguồn kèm theo. Hãy tôn trọng tác giả bài tập và người viết hướng dẫn giải.
Nộp mã nguồn lời giải chính thức trước khi giải bài tập đó có thể khiến bạn bị ban.

Tác giả: kienadmin

Hướng dẫn giải: Truy Vấn Điểm Thuộc Đoạn

Phân tích bài toán

Một điểm \(X\) thuộc đoạn \([L_i, R_i]\) nếu và chỉ nếu \(L_i \le X \le R_i\). Truy vấn này tương đương với việc tìm tất cả các đoạn thẳng giao với đoạn truy vấn có độ dài bằng 0 là \([X, X]\). Ta áp dụng trực tiếp cấu trúc dữ liệu Interval Tree tĩnh tương tự bài liệt kê toàn bộ đoạn giao nhau, với tham số truy vấn là \([X, X]\).

Độ phức tạp
  • Thời gian: \(O(N \log N)\) xây dựng cây. Mỗi truy vấn thực hiện trong \(O(\log N + k)\) với \(k\) là số lượng đoạn thẳng chứa điểm \(X\).
  • Không gian: \(O(N \log N)\) bộ nhớ.
Mã nguồn C++ mẫu
#include <bits/stdc++.h>
using namespace std;

struct IntervalTree {
    struct Node {
        int median;
        vector<pair<int,int>> S1;
        vector<pair<int,int>> S2;
        Node *left = nullptr, *right = nullptr;
    };

    Node* root;

    Node* build(vector<pair<int,int>>& intervals) {
        if (intervals.empty()) return nullptr;
        Node* node = new Node();
        vector<int> lvals;
        for (auto& [l, r] : intervals) lvals.push_back(l);
        sort(lvals.begin(), lvals.end());
        node->median = lvals[lvals.size() / 2];

        vector<pair<int,int>> leftSet, rightSet;
        for (auto& [l, r] : intervals) {
            if (r < node->median) leftSet.push_back({l, r});
            else if (l > node->median) rightSet.push_back({l, r});
            else {
                node->S1.push_back({l, r});
                node->S2.push_back({l, r});
            }
        }
        sort(node->S1.begin(), node->S1.end());
        sort(node->S2.begin(), node->S2.end(), [](auto& a, auto& b) {
            return a.second > b.second;
        });
        node->left = build(leftSet);
        node->right = build(rightSet);
        return node;
    }

    IntervalTree(vector<pair<int,int>>& intervals) {
        root = build(intervals);
    }

    void query(Node* node, int x, int& count, long long& sum_val) {
        if (!node) return;
        const int MOD = 1e9 + 7;
        if (x < node->median) {
            for (auto& seg : node->S1) {
                if (seg.first <= x) {
                    count++;
                    long long term = (1LL * (seg.first % MOD + MOD) % MOD * ((seg.second % MOD + MOD) % MOD)) % MOD;
                    sum_val = (sum_val + term) % MOD;
                }
                else break;
            }
            query(node->left, x, count, sum_val);
        } else if (x > node->median) {
            for (auto& seg : node->S2) {
                if (seg.second >= x) {
                    count++;
                    long long term = (1LL * (seg.first % MOD + MOD) % MOD * ((seg.second % MOD + MOD) % MOD)) % MOD;
                    sum_val = (sum_val + term) % MOD;
                }
                else break;
            }
            query(node->right, x, count, sum_val);
        } else {
            for (auto& seg : node->S1) {
                count++;
                long long term = (1LL * (seg.first % MOD + MOD) % MOD * ((seg.second % MOD + MOD) % MOD)) % MOD;
                sum_val = (sum_val + term) % MOD;
            }
            query(node->left, x, count, sum_val);
            query(node->right, x, count, sum_val);
        }
    }
};

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    int n, q;
    if (!(cin >> n >> q)) return 0;
    vector<pair<int,int>> intervals(n);
    for (int i = 0; i < n; i++) {
        cin >> intervals[i].first >> intervals[i].second;
    }
    IntervalTree tree(intervals);
    while (q--) {
        int x;
        cin >> x;
        int count = 0;
        long long sum_val = 0;
        tree.query(tree.root, x, count, sum_val);
        cout << count << " " << sum_val << "\n";
    }
    return 0;
}

Nhận xét

Không có ý kiến tại thời điểm này.