Submission #1369486

#TimeUsernameProblemLanguageResultExecution timeMemory
1369486LOLOLORadio (COCI22_radio)C++17
110 / 110
502 ms146608 KiB
#include <bits/stdc++.h>
using namespace std;

const int INF = 1e9;

struct SegmentTree {
    int n;
    vector<int> st;

    SegmentTree(int _n = 0) {
        init(_n);
    }

    void init(int _n) {
        n = 1;
        while (n < _n) n <<= 1;
        st.assign(2 * n, INF);
    }

    void update(int pos, int val) {
        pos += n - 1;
        st[pos] = val;
        pos >>= 1;

        while (pos > 0) {
            st[pos] = min(st[pos << 1], st[pos << 1 | 1]);
            pos >>= 1;
        }
    }

    int query(int l, int r) {
        l += n - 1;
        r += n - 1;

        int ans = INF;

        while (l <= r) {
            if (l & 1) ans = min(ans, st[l++]);
            if (!(r & 1)) ans = min(ans, st[r--]);
            l >>= 1;
            r >>= 1;
        }

        return ans;
    }
};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, q;
    cin >> n >> q;

    vector<int> spf(n + 1);

    for (int i = 1; i <= n; i++) {
        spf[i] = i;
    }

    for (int i = 2; i * i <= n; i++) {
        if (spf[i] == i) {
            for (long long j = 1LL * i * i; j <= n; j += i) {
                if (spf[j] == j) {
                    spf[j] = i;
                }
            }
        }
    }

    auto getPrimeFactors = [&](int x) {
        vector<int> factors;

        while (x > 1) {
            int p = spf[x];
            factors.push_back(p);

            while (x % p == 0) {
                x /= p;
            }
        }

        return factors;
    };

    vector< set<int> > byPrime(n + 1);
    vector< multiset<int> > pairEnd(n + 1);
    vector<char> active(n + 1, false);

    SegmentTree seg(n);

    auto setLeaf = [&](int u) {
        if (pairEnd[u].empty()) {
            seg.update(u, INF);
        } else {
            seg.update(u, *pairEnd[u].begin());
        }
    };

    auto addPair = [&](int u, int v) {
        pairEnd[u].insert(v);
        setLeaf(u);
    };

    auto removePair = [&](int u, int v) {
        auto it = pairEnd[u].find(v);
        if (it != pairEnd[u].end()) {
            pairEnd[u].erase(it);
        }
        setLeaf(u);
    };

    auto addNumber = [&](int x) {
        vector<int> primes = getPrimeFactors(x);

        for (int p : primes) {
            auto &s = byPrime[p];

            auto itRight = s.lower_bound(x);

            bool hasLeft = false;
            bool hasRight = false;

            int leftValue = -1;
            int rightValue = -1;

            if (itRight != s.end()) {
                hasRight = true;
                rightValue = *itRight;
            }

            if (itRight != s.begin()) {
                hasLeft = true;
                auto itLeft = prev(itRight);
                leftValue = *itLeft;
            }

            if (hasLeft && hasRight) {
                removePair(leftValue, rightValue);
            }

            if (hasLeft) {
                addPair(leftValue, x);
            }

            if (hasRight) {
                addPair(x, rightValue);
            }

            s.insert(x);
        }
    };

    auto removeNumber = [&](int x) {
        vector<int> primes = getPrimeFactors(x);

        for (int p : primes) {
            auto &s = byPrime[p];

            auto it = s.find(x);

            bool hasLeft = false;
            bool hasRight = false;

            int leftValue = -1;
            int rightValue = -1;

            if (it != s.begin()) {
                hasLeft = true;
                auto itLeft = prev(it);
                leftValue = *itLeft;
            }

            auto itRight = next(it);
            if (itRight != s.end()) {
                hasRight = true;
                rightValue = *itRight;
            }

            if (hasLeft) {
                removePair(leftValue, x);
            }

            if (hasRight) {
                removePair(x, rightValue);
            }

            if (hasLeft && hasRight) {
                addPair(leftValue, rightValue);
            }

            s.erase(it);
        }
    };

    while (q--) {
        char type;
        cin >> type;

        if (type == 'S') {
            int x;
            cin >> x;

            if (!active[x]) {
                active[x] = true;
                addNumber(x);
            } else {
                active[x] = false;
                removeNumber(x);
            }
        } else {
            int l, r;
            cin >> l >> r;

            int minRight = seg.query(l, r);

            if (minRight <= r) {
                cout << "DA\n";
            } else {
                cout << "NE\n";
            }
        }
    }

    return 0;
}
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...