Problem:
G: エレベータ
問題
株式会社AORは $N$ 階建てのビルである。地下階は存在しない。
AORイカちゃんはイカであるため、階段を下りることは可能だが、上ることは不可能である。
上の階に登れないと不便なため、$M$ 個のエレベータをビルに設置することにした。
エレベータを設置するには時間がかかり、$i$ 番目のエレベータは $D_i$ 日後の夜に設置が完了し、 $A_i$ 階以上 $B_i$ 階以下の全ての階を移動可能にする。
あなたはAORイカちゃんに $Q$ 個の質問をされた。$i$ 番目の質問は「 $E_i$ 日後の昼に、$S_i$ 階から $T_i$ 階に移動可能か？」という質問である。
移動に使える手段は階段とエレベータのみである。また移動にかかる時間は無視できるものとする。
制約
$2 \le N \le 10^5$
$1 \le M \le 10^5$
$1 \le Q \le 10^5$
$1 \le D_i , E_i \le 10^9$
$1 \le A_i < B_i \le N$
$1 \le S_i , T_i \le N$
入力は全て整数
入力
$N \ M\ Q$
$D_1 \ A_1 \ B_1$
$\vdots$
$D_M \ A_M \ B_M$
$E_1 \ S_1 \ T_1$
$\vdots$
$E_Q \ S_Q \ T_Q$
出力
各質問ごとに一行で
Yes
または
No
を出力せよ。ただし質問された順に答えること。また末尾に改行を出力せよ。
サンプル
サンプル入力 1
5 1 2
3 1 5
3 1 5
4 1 5
サンプル出力 1
No
Yes
エレベータが設置されるのは三日目の夜であるため、三日目の昼に移動することはできない。
サンプル入力 2
8 6 5
30 6 7
21 3 8
5 2 4
10 1 2
2 7 8
15 5 7
16 5 8
11 1 3
22 3 7
30 6 7
15 5 8
サンプル出力 2
Yes
Yes
Yes
Yes
No

Submitted solutions:

code_snippet: //
// 区間 (と値) を Set で管理する構造体
//
// verified
//   第六回 アルゴリズム実技検定 M - 等しい数 (for update)
//     https://atcoder.jp/contests/past202104-open/tasks/past202104_m
//
//   RUPC 2018 G - Elevator (for insert, same)
//     https://onlinejudge.u-aizu.ac.jp/problems/2880 
//
//   AtCoder ABC 255 Ex - Range Harvest Query (for update)
//     https://atcoder.jp/contests/abc255/tasks/abc255_h 
//
//   yukicoder No.674 n連勤 (for insert)
//     https://yukicoder.me/problems/no/674 
//
//   AtCoder ABC 330 E - Mex and Update (for insert, erase, mex)
//     https://atcoder.jp/contests/abc330/tasks/abc330_e 
//
//   第五回 アルゴリズム実技検定 N - 旅行会社 (for insert, erase, lower_bound)
//     https://atcoder.jp/contests/past202012-open/tasks/past202012_n
//
//   Code Festival 2015 予選 B D - マスと駒と色塗り (for insert, lower_bound)
//     https://atcoder.jp/contests/code-festival-2015-qualb/tasks/codefestival_2015_qualB_d
//
//   CPSCO 2019 Session 1 E - Exclusive OR Queries (for insert with del, lower_bound)
//     https://atcoder.jp/contests/cpsco2019-s1/tasks/cpsco2019_s1_e
//
//   yukicoder No.3017 交互浴 (for update)
//     https://yukicoder.me/problems/no/3017 
//
//   KUPC 2018 I - League of Kyoto (for insert, erase with add, del)(maybe, the strongest data set for erase)
//     https://atcoder.jp/contests/kupc2018/tasks/kupc2018_i 
//


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


// Interval Set
// T: type of range, VAL: data type
template<class T, class VAL = long long> struct IntervalSet {
    struct Node {
        T l, r;
        VAL val;
        Node(const T &l, const T &r, const VAL &val) : l(l), r(r), val(val) {}
        constexpr bool operator < (const Node &rhs) const {
            if (l != rhs.l) return l < rhs.l;
            else return r < rhs.r;
        }
        friend ostream& operator << (ostream &s, const Node &e) {
            return s << "([" << e.l << ", " << e.r << "): " << e.val << ")";
        }
    };

    // internal values
    const VAL identity;
    set<Node> S;

    // constructor
    IntervalSet(const VAL &identity = VAL()) : identity(identity) {}
    IntervalSet(const vector<VAL> &v, const VAL &identity = VAL()) : identity(identity) {
        vector<Node> vec;
        for (int l = 0; l < (int)v.size();) {
            int r = l;
            while (r < (int)v.size() && v[r] == v[l]) r++;
            vec.emplace_back(l, r, v[l]);
            l = r;
        }
        S = set<Node>(vec.begin(), vec.end());
    }

    // get the basic iterators
    constexpr typename set<Node>::iterator begin() { return S.begin(); }
    constexpr typename set<Node>::iterator end() { return S.end(); }

    // get the iterator of interval which contains p
    // not exist -> S.end()
    constexpr typename set<Node>::iterator get(const T &p) {
        auto it = S.upper_bound(Node(p, numeric_limits<T>::max(), 0));
        if (it == S.begin()) return S.end();
        it = prev(it);
        if (it->l <= p && p < it->r) return it;
        else return S.end();
    }

    // get the leftist iterator of interval which contains value >= p
    constexpr typename set<Node>::iterator lower_bound(const T &p) {
        auto it = get(p);
        if (it != S.end()) return it;
        return S.upper_bound(Node(p, numeric_limits<T>::max(), 0));
    }
    
    // exist the interval which contains p: true, [l, r): true
    constexpr bool covered(const T &p) {
        auto it = get(p);
        if (it != S.end()) return true;
        else return false;
    }
    constexpr bool covered(const T &l, const T &r) {
        assert(l <= r);
        if (l == r) return true;
        auto it = get(l);
        if (it != S.end() && r <= it->r) return true;
        else return false;
    }

    // is p, q in same interval?
    constexpr bool same(const T &p, const T &q) {
        if (!covered(p) || !covered(q)) return false;
        return get(p) == get(q);
    }

    // get the value of interval which contains p
    // not exist -> identity
    constexpr VAL get_val(const T &p) {
        auto it = get(p);
        if (it != S.end()) return it->val;
        else return identity;
    }
    VAL operator [] (const T &p) const {
        return get_val(p);
    }

    // get mex (>= p)
    constexpr T get_mex(const T &p = 0) {
        auto it = S.upper_bound(Node(p, numeric_limits<T>::max(), 0));
        if (it == S.begin()) return p;
        it = prev(it); 
        if (it->l <= p && p < it->r) return it->r;
        else return p;
    }

    // update [l, r) with value val / insert [l, r)
    // del: reflect effects of interval-delete
    // add: reflect effects of interval add
    template<class ADDFUNC, class DELFUNC> void update(T l, T r, const VAL &val, const ADDFUNC &add, const DELFUNC &del) {
        auto it = S.lower_bound(Node(l, 0, val));
        while (it != S.end() && it->l <= r) {
            if (it->l == r) {
                if (it->val ==val) {
                    r = it->r;
                    del(it->l, it->r, it->val);
                    it = S.erase(it);
                }
                break;
            }
            if (it->r <= r) {
                del(it->l, it->r, it->val);
                it = S.erase(it);
            } else {
                if (it->val == val) {
                    r = it->r;
                    del(it->l, it->r, it->val);
                    it = S.erase(it);
                } else {
                    Node node = *it;
                    del(it->l, it->r, it->val);
                    it = S.erase(it);
                    it = S.emplace_hint(it, r, node.r, node.val);
                    add(it->l, it->r, it->val);
                }
            }
        }
        if (it != S.begin()) {
            it = prev(it);
            if (it->r == l) {
                if (it->val == val) {
                    l = it->l;
                    del(it->l, it->r, it->val);
                    it = S.erase(it);
                }
            } else if (l < it->r) {
                if (it->val == val) {
                    l = min(l, it->l);
                    r = max(r, it->r);
                    del(it->l, it->r, it->val);
                    it = S.erase(it);
                } else {
                    if (r < it->r) {
                        it = S.emplace_hint(next(it), r, it->r, it->val);
                        add(it->l, it->r, it->val);
                        it = prev(it);
                    }
                    Node node = *it;
                    del(it->l, it->r, it->val);
                    it = S.erase(it);
                    it = S.emplace_hint(it, node.l, l, node.val);
                    add(it->l, it->r, it->val);
                }
            }
        }
        if (it != S.end()) it = next(it);
        it = S.emplace_hint(it, l, r, val);
        add(it->l, it->r, it->val);
    }
    void update(const T &l, const T &r, const VAL &val) {
        update(l, r, val, [](T, T, VAL){}, [](T, T, VAL){});
    }
    template<class ADDFUNC, class DELFUNC> void insert(T l, T r, const ADDFUNC &add, const DELFUNC &del) {
        update(l, r, VAL(), add, del);
    }
    void insert(const T &l, const T &r) {
        update(l, r, VAL(), [](T, T, VAL){}, [](T, T, VAL){});
    }

    // erase [l, r)
    template<class ADDFUNC, class DELFUNC> void erase(T l, T r, const ADDFUNC &add, const DELFUNC &del) {
        auto it = S.lower_bound(Node(l, 0, VAL()));
        //COUT(*it);
        while (it != S.end() && it->l <= r) {
            if (it->l == r) break;
            if (it->r <= r) {
                del(it->l, it->r, it->val);
                it = S.erase(it);
            } else {
                Node node = *it;
                del(it->l, it->r, it->val);
                it = S.erase(it);
                it = S.emplace_hint(it, r, node.r, node.val);
                add(it->l, it->r, it->val);
            }
        }
        if (it != S.begin()) {
            it = prev(it);
            if (l < it->r) {
                if (r < it->r) {
                    it = S.emplace_hint(next(it), r, it->r, it->val);
                    add(it->l, it->r, it->val);
                    it = prev(it);
                }
                Node node = *it;
                //COUT(*it);
                del(it->l, it->r, it->val);
                it = S.erase(it);
                it = S.emplace_hint(it, node.l, l, node.val);
                add(it->l, it->r, it->val);
                //COUT(*it);
            }
        }
    }
    void erase(const T &l, const T &r) {
        erase(l, r, [](T, T, VAL){}, [](T, T, VAL){});
    }

    // debug
    friend ostream& operator << (ostream &s, const IntervalSet &ins) {
        for (auto e : ins.S) {
            s << "([" << e.l << ", " << e.r << "): " << e.val << ") ";
        }
        return s;
    }
};


/*/////////////////////////////*/
// Solver
/*/////////////////////////////*/

// 第六回 アルゴリズム実技検定 M - 等しい数
void PAST_6_M() {
    long long N, Q;
    cin >> N;
    vector<long long> A(N);
    map<long long, long long> cnt;
    for (int i = 0; i < N; i++) {
        cin >> A[i];
        cnt[A[i]]++;
    }
    long long res = 0;
    for (auto [val, num] : cnt) res += num * (num - 1) / 2;

    auto add = [&](int l, int r, long long val) -> void {
        long long before = cnt[val] * (cnt[val] - 1) / 2;
        cnt[val] += r - l;
        long long after = cnt[val] * (cnt[val] - 1) / 2;
        res += after - before;
    };
    auto del = [&](int l, int r, long long val) -> void {
        long long before = cnt[val] * (cnt[val] - 1) / 2;
        cnt[val] -= r - l;
        long long after = cnt[val] * (cnt[val] - 1) / 2;
        res += after - before;
    };
    IntervalSet<int, long long> ins(A);

    cin >> Q;
    while (Q--) {
        int l, r;
        long long val;
        cin >> l >> r >> val;
        l--;
        ins.update(l, r, val, add, del);
        cout << res << '\n';
    }
}

// RUPC 2018 G - Elevator
void RUPC_2018_G() {
    using fll = array<long long, 4>;
    int N, M, Q, t, l, r;
    cin >> N >> M >> Q;
    vector<fll> qs(M + Q);
    for (int i = 0; i < M; i++) {
        cin >> t >> l >> r, l--, r--;
        qs[i] = fll({-1, t*2+1, l*2, r*2+1});
    }
    for (int i = 0; i < Q; i++) {
        cin >> t >> l >> r, l--, r--;
        qs[i+M] = fll({i, t*2, l*2, r*2});
    }
    sort(qs.begin(), qs.end(), [&](const fll &p, const fll &q) { return p[1] < q[1]; });

    IntervalSet<long long> ins;
    vector<bool> res(Q, false);
    for (auto q : qs) {
        if (q[0] == -1) {
            ins.insert(q[2], q[3]);
        } else {
            if (q[2] >= q[3] || ins.same(q[2], q[3])) res[q[0]] = true;
            else res[q[0]] = false;
        }
    }
    for (int q = 0; q < Q; ++q) cout << (res[q] ? "Yes" : "No") << endl;
}

// AtCoder ABC 255 Ex - Range Harvest Query
// modint
template<int MOD> struct Fp {
    // inner value
    long long val;
    
    // constructor
    constexpr Fp() : val(0) { }
    constexpr Fp(long long v) : val(v % MOD) {
        if (val < 0) val += MOD;
    }
    constexpr long long get() const { return val; }
    constexpr int get_mod() const { return MOD; }
    
    // arithmetic operators
    constexpr Fp operator + () const { return Fp(*this); }
    constexpr Fp operator - () const { return Fp(0) - Fp(*this); }
    constexpr Fp operator + (const Fp &r) const { return Fp(*this) += r; }
    constexpr Fp operator - (const Fp &r) const { return Fp(*this) -= r; }
    constexpr Fp operator * (const Fp &r) const { return Fp(*this) *= r; }
    constexpr Fp operator / (const Fp &r) const { return Fp(*this) /= r; }
    constexpr Fp& operator += (const Fp &r) {
        val += r.val;
        if (val >= MOD) val -= MOD;
        return *this;
    }
    constexpr Fp& operator -= (const Fp &r) {
        val -= r.val;
        if (val < 0) val += MOD;
        return *this;
    }
    constexpr Fp& operator *= (const Fp &r) {
        val = val * r.val % MOD;
        return *this;
    }
    constexpr Fp& operator /= (const Fp &r) {
        long long a = r.val, b = MOD, u = 1, v = 0;
        while (b) {
            long long t = a / b;
            a -= t * b, swap(a, b);
            u -= t * v, swap(u, v);
        }
        val = val * u % MOD;
        if (val < 0) val += MOD;
        return *this;
    }
    constexpr Fp pow(long long n) const {
        Fp res(1), mul(*this);
        while (n > 0) {
            if (n & 1) res *= mul;
            mul *= mul;
            n >>= 1;
        }
        return res;
    }
    constexpr Fp inv() const {
        Fp res(1), div(*this);
        return res / div;
    }

    // other operators
    constexpr bool operator == (const Fp &r) const {
        return this->val == r.val;
    }
    constexpr bool operator != (const Fp &r) const {
        return this->val != r.val;
    }
    constexpr Fp& operator ++ () {
        ++val;
        if (val >= MOD) val -= MOD;
        return *this;
    }
    constexpr Fp& operator -- () {
        if (val == 0) val += MOD;
        --val;
        return *this;
    }
    constexpr Fp operator ++ (int) const {
        Fp res = *this;
        ++*this;
        return res;
    }
    constexpr Fp operator -- (int) const {
        Fp res = *this;
        --*this;
        return res;
    }
    friend constexpr istream& operator >> (istream &is, Fp<MOD> &x) {
        is >> x.val;
        x.val %= MOD;
        if (x.val < 0) x.val += MOD;
        return is;
    }
    friend constexpr ostream& operator << (ostream &os, const Fp<MOD> &x) {
        return os << x.val;
    }
    friend constexpr Fp<MOD> pow(const Fp<MOD> &r, long long n) {
        return r.pow(n);
    }
    friend constexpr Fp<MOD> inv(const Fp<MOD> &r) {
        return r.inv();
    }
};
void ABC_255_Ex() {
    const int MOD = 998244353;
    const long long INF = 1LL << 60;
    using mint = Fp<MOD>;

    long long N, Q, D, L, R;
    cin >> N >> Q;
    mint res = 0;
    auto add = [&](long long l, long long r, long long val) -> void {};
    auto del = [&](long long l, long long r, long long val) -> void {
        res += mint(D - val) * (l + r - 1) * (r - l) / 2;
    };
    IntervalSet<long long, long long> ins;
    ins.update(0, INF, 0);
    while (Q--) {
        cin >> D >> L >> R;
        res = 0;
        ins.update(L, R+1, D, add, del);
        cout << res << '\n';
    }
}

// yukicoder No.674 n連勤
void yukicoder_674() {
    long long D, Q, A, B;
    cin >> D >> Q;
    IntervalSet<long long> ins;
    long long res = 0;
    while (Q--) {
        cin >> A >> B;
        ins.insert(A, B+1);
        auto it = ins.get(A);
        long long l = it->l, r = it->r;
        res = max(res, r - l);
        cout << res << '\n';
    }
}

// AtCoder ABC 330 E - Mex and Update
void ABC_330_E() {
    int N, Q, i, x;
    cin >> N >> Q;
    vector<int> A(N);
    map<int, int> mp;
    IntervalSet<int> ins;
    for (int i = 0; i < N; i++) {
        cin >> A[i];
        mp[A[i]]++;
        ins.insert(A[i], A[i]+1);
    }
    while (Q--) {
        cin >> i >> x;
        i--;
        mp[A[i]]--;
        if (mp[A[i]] == 0) ins.erase(A[i], A[i]+1);
        A[i] = x;
        mp[A[i]]++;
        ins.insert(A[i], A[i]+1);
        cout << ins.get_mex() << '\n';
    }
}

// 第五回 アルゴリズム実技検定 N - 旅行会社
void PAST_5_N() {
    const int IN = -2;
    const int OUT = -1;
    using tint = array<int, 3>;  // (time, type(0, 1, 2), city)
    int N, Q;
    cin >> N >> Q;
    vector<tint> events;
    for (int i = 0; i < N-1; i++) {
        int L, R;
        cin >> L >> R;
        L--;
        events.push_back({L, IN, i});
        events.push_back({R, OUT, i});
    }
    for (int i = 0; i < Q; i++) {
        int A, B;
        cin >> A >> B;
        A--, B--;
        events.push_back({A, i, B});
    }
    sort(events.begin(), events.end());

    IntervalSet<int> ins;
    vector<int> res(Q);
    for (auto [time, id, city] : events) {
        if (id == IN) {
            ins.insert(city, city+1);
        } else if (id == OUT) {
            ins.erase(city, city+1);
        } else {
            int ma = city, mi = city;
            auto it = ins.lower_bound(city);
            if (it != ins.end()) {
                if (city >= it->l) ma = max(ma, it->r), mi = min(mi, it->l);
            }
            if (it != ins.begin()) {
                it = prev(it);
                if (city <= it->r) mi = min(mi, it->l);
            }
            res[id] = ma - mi + 1;
        }
    }
    for (auto val : res) cout << val << '\n';
}

// Code Festival 2015 予選 B D - マスと駒と色塗り (for insert, lower_bound)
void code_festival_2015_B_D() {
    long long N, S, C;
    cin >> N;

    const long long INF = 1LL<<60;
    IntervalSet<long long> ins;
    ins.insert(INF, INF*2);
    while (N--) {
        cin >> S >> C;
        S--;
        long long cur = S;
        while (C > 0) {
            auto it = ins.lower_bound(cur);
            if (cur >= it->l) cur = it->r;
            else {
                long long diff = it->l - cur;
                cur += min(diff, C);
                C -= min(diff, C);
            }
        }
        ins.insert(S, cur);
        cout << cur << '\n';
    }
}

// CPSCO 2019 Session 1 E - Exclusive OR Queries
void cpsco_2019_session_1_E() {
    long long N, Q, A, L, R, X;
    cin >> N >> Q;
    set<long long> se;
    for (int i = 0; i < N; i++) {
        cin >> A;
        if (se.count(A)) se.erase(A);
        else se.insert(A);
    }
    long long res = 0, num = 0;
    auto add = [&](long long l, long long r, long long val) -> void {
        for (long long k = l; k < r; k++) res ^= k, num--;
    };
    auto del = [&](long long l, long long r, long long val) -> void {
        for (long long k = l; k < r; k++) res ^= k, num++;
    };
    IntervalSet<long long, long long> ins;
    for (auto val : se) ins.update(val, val+1, 1);
    while (Q--) {
        cin >> L >> R >> X;
        R++;
        res = 0, num = 0;
        ins.erase(L, R, add, del);
        cout << res << '\n';
        int exist = ins.covered(X);
        if ((num + exist) % 2 == 1) ins.update(X, X+1, 1);
        else ins.erase(X, X+1);
    }
}

// yukicoder No.3017 交互浴
void yukicoder_3017() {
    long long N, H;
    cin >> N;

    long long res = 0;
    auto add = [&](long long l, long long r, long long val) -> void {
        res += (r - l) * val;
    };
    auto del = [&](long long l, long long r, long long val) -> void {
        res -= (r - l) * val;
    };
    IntervalSet<long long, long long> ins;
    for (int iter = 0; iter < N; iter++) {
        cin >> H;
        if (iter % 2 == 0) ins.update(0, H, 1, add, del);
        else ins.update(0, H, 0, add, del);
        cout << res << '\n';
    }
}

// KUPC 2018 I - League of Kyoto
template<class Monoid, class Action> struct LazySegmentTree {
    // various function types
    using FuncMonoid = function<Monoid(Monoid, Monoid)>;
    using FuncAction = function<Monoid(Action, Monoid)>;
    using FuncComposition = function<Action(Action, Action)>;

    // core member
    int N;
    FuncMonoid OP;
    FuncAction ACT;
    FuncComposition COMP;
    Monoid IDENTITY_MONOID;
    Action IDENTITY_ACTION;
    
    // inner data
    int log, offset;
    vector<Monoid> dat;
    vector<Action> lazy;
    
    // constructor
    LazySegmentTree() {}
    LazySegmentTree(int n, const FuncMonoid op, const FuncAction act, const FuncComposition comp,
                    const Monoid &identity_monoid, const Action &identity_action) {
        init(n, op, act, comp, identity_monoid, identity_action);
    }
    LazySegmentTree(const vector<Monoid> &v,
                    const FuncMonoid op, const FuncAction act, const FuncComposition comp,
                    const Monoid &identity_monoid, const Action &identity_action) {
        init(v, op, act, comp, identity_monoid, identity_action);
    }
    void init(int n, const FuncMonoid op, const FuncAction act, const FuncComposition comp,
              const Monoid &identity_monoid, const Action &identity_action) {
        N = n, OP = op, ACT = act, COMP = comp;
        IDENTITY_MONOID = identity_monoid, IDENTITY_ACTION = identity_action;
        log = 0, offset = 1;
        while (offset < N) ++log, offset <<= 1;
        dat.assign(offset * 2, IDENTITY_MONOID);
        lazy.assign(offset * 2, IDENTITY_ACTION);
    }
    void init(const vector<Monoid> &v,
              const FuncMonoid op, const FuncAction act, const FuncComposition comp,
              const Monoid &identity_monoid, const Action &identity_action) {
        init((int)v.size(), op, act, comp, identity_monoid, identity_action);
        build(v);
    }
    void build(const vector<Monoid> &v) {
        assert(N == (int)v.size());
        for (int i = 0; i < N; ++i) dat[i + offset] = v[i];
        for (int k = offset - 1; k > 0; --k) pull_dat(k);
    }
    int size() const {
        return N;
    }
    
    // basic functions for lazy segment tree
    void pull_dat(int k) {
        dat[k] = OP(dat[k * 2], dat[k * 2 + 1]);
    }
    void apply_lazy(int k, const Action &f) {
        dat[k] = ACT(f, dat[k]);
        if (k < offset) lazy[k] = COMP(f, lazy[k]);
    }
    void push_lazy(int k) {
        apply_lazy(k * 2, lazy[k]);
        apply_lazy(k * 2 + 1, lazy[k]);
        lazy[k] = IDENTITY_ACTION;
    }
    void pull_dat_deep(int k) {
        for (int h = 1; h <= log; ++h) pull_dat(k >> h);
    }
    void push_lazy_deep(int k) {
        for (int h = log; h >= 1; --h) push_lazy(k >> h);
    }
    
    // setter and getter, update A[i], i is 0-indexed, O(log N)
    void set(int i, const Monoid &v) {
        assert(0 <= i && i < N);
        int k = i + offset;
        push_lazy_deep(k);
        dat[k] = v;
        pull_dat_deep(k);
    }
    Monoid get(int i) {
        assert(0 <= i && i < N);
        int k = i + offset;
        push_lazy_deep(k);
        return dat[k];
    }
    Monoid operator [] (int i) {
        return get(i);
    }
    
    // apply f for index i
    void apply(int i, const Action &f) {
        assert(0 <= i && i < N);
        int k = i + offset;
        push_lazy_deep(k);
        dat[k] = ACT(f, dat[k]);
        pull_dat_deep(k);
    }
    // apply f for interval [l, r)
    void apply(int l, int r, const Action &f) {
        assert(0 <= l && l <= r && r <= N);
        if (l == r) return;
        l += offset, r += offset;
        for (int h = log; h >= 1; --h) {
            if (((l >> h) << h) != l) push_lazy(l >> h);
            if (((r >> h) << h) != r) push_lazy((r - 1) >> h);
        }
        int original_l = l, original_r = r;
        for (; l < r; l >>= 1, r >>= 1) {
            if (l & 1) apply_lazy(l++, f);
            if (r & 1) apply_lazy(--r, f);
        }
        l = original_l, r = original_r;
        for (int h = 1; h <= log; ++h) {
            if (((l >> h) << h) != l) pull_dat(l >> h);
            if (((r >> h) << h) != r) pull_dat((r - 1) >> h);
        }
    }
    
    // get prod of interval [l, r)
    Monoid prod(int l, int r) {
        assert(0 <= l && l <= r && r <= N);
        if (l == r) return IDENTITY_MONOID;
        l += offset, r += offset;
        for (int h = log; h >= 1; --h) {
            if (((l >> h) << h) != l) push_lazy(l >> h);
            if (((r >> h) << h) != r) push_lazy(r >> h);
        }
        Monoid val_left = IDENTITY_MONOID, val_right = IDENTITY_MONOID;
        for (; l < r; l >>= 1, r >>= 1) {
            if (l & 1) val_left = OP(val_left, dat[l++]);
            if (r & 1) val_right = OP(dat[--r], val_right);
        }
        return OP(val_left, val_right);
    }
    Monoid all_prod() {
        return dat[1];
    }
    
    // get max r that f(get(l, r)) = True (0-indexed), O(log N)
    // f(IDENTITY) need to be True
    int max_right(const function<bool(Monoid)> f, int l = 0) {
        if (l == N) return N;
        l += offset;
        push_lazy_deep(l);
        Monoid sum = IDENTITY_MONOID;
        do {
            while (l % 2 == 0) l >>= 1;
            if (!f(OP(sum, dat[l]))) {
                while (l < offset) {
                    push_lazy(l);
                    l = l * 2;
                    if (f(OP(sum, dat[l]))) {
                        sum = OP(sum, dat[l]);
                        ++l;
                    }
                }
                return l - offset;
            }
            sum = OP(sum, dat[l]);
            ++l;
        } while ((l & -l) != l);  // stop if l = 2^e
        return N;
    }

    // get min l that f(get(l, r)) = True (0-indexed), O(log N)
    // f(IDENTITY) need to be True
    int min_left(const function<bool(Monoid)> f, int r = -1) {
        if (r == 0) return 0;
        if (r == -1) r = N;
        r += offset;
        push_lazy_deep(r - 1);
        Monoid sum = IDENTITY_MONOID;
        do {
            --r;
            while (r > 1 && (r % 2)) r >>= 1;
            if (!f(OP(dat[r], sum))) {
                while (r < offset) {
                    push_lazy(r);
                    r = r * 2 + 1;
                    if (f(OP(dat[r], sum))) {
                        sum = OP(dat[r], sum);
                        --r;
                    }
                }
                return r + 1 - offset;
            }
            sum = OP(dat[r], sum);
        } while ((r & -r) != r);
        return 0;
    }
    
    // debug stream
    friend ostream& operator << (ostream &s, LazySegmentTree seg) {
        for (int i = 0; i < (int)seg.size(); ++i) {
            s << seg[i];
            if (i != (int)seg.size() - 1) s << " ";
        }
        return s;
    }
    
    // dump
    void dump() {
        for (int i = 0; i <= log; ++i) {
            for (int j = (1 << i); j < (1 << (i + 1)); ++j) {
                cout << "{" << dat[j] << "," << lazy[j] << "} ";
            }
            cout << endl;
        }
    }
};
void KUPC_2018_I() {
    int N, M, Q;
    cin >> N >> M;
    vector<int> L(M), R(M), S(M);
    for (int i = 0; i < M; i++) cin >> L[i] >> R[i] >> S[i], L[i]--;
    cin >> Q;
    vector<int> typ(Q), L2(Q), R2(Q);
    for (int q = 0; q < Q; q++) cin >> typ[q] >> L2[q] >> R2[q], L2[q]--;

    IntervalSet<int> ins;
    ins.insert(0, N);
    vector<vector<pair<int,int>>> adds(Q), dels(Q);
    int q = 0;
    auto add = [&](int l, int r, int v) -> void { dels[q].emplace_back(l, r); };
    auto del = [&](int l, int r, int v) -> void { adds[q].emplace_back(l, r); };
    for (; q < Q; q++) {
        if (typ[q] == 0) ins.insert(L2[q], R2[q], add, del);
        else ins.erase(L2[q], R2[q], add, del);
    }

    auto op = [&](long long p, long long q) -> long long { return max(p, q); };
    auto mapping = [&](long long f, long long v) -> long long { return v + f; };
    auto composition = [&](long long g, long long f) -> long long { return f + g; };
    LazySegmentTree<long long, long long> seg(N, op, mapping, composition, 0, 0);
    vector<vector<pair<int,int>>> enemy(N);
    for (int i = 0; i < M; i++) {
        enemy[L[i]].emplace_back(R[i], S[i]);
        seg.apply(R[i]-1, N, S[i]);
    }
    map<pair<int,int>, long long> score;

    vector<vector<int>> inters(N);
    for (int q = 0; q < Q; q++) {
        for (auto [l, r] : adds[q]) inters[l].emplace_back(r);
        for (auto [l, r] : dels[q]) inters[l].emplace_back(r);
    }
    for (int l = 0; l < N; l++) {
        for (auto r : inters[l]) {
            score[make_pair(l, r)] = seg.prod(l, r);
        }
        for (auto [r, s] : enemy[l]) {
            seg.apply(r-1, N, -s);
        }
    }

    long long res = 0;
    for (int q = 0; q < Q; q++) {
        for (auto [l, r] : adds[q]) res += score[make_pair(l, r)];
        for (auto [l, r] : dels[q]) res -= score[make_pair(l, r)];
        cout << res << '\n';
    }
}


int main() {
    //PAST_6_M();
    RUPC_2018_G();
    //ABC_255_Ex();
    //yukicoder_674();
    //ABC_330_E();
    //PAST_5_N();
    //code_festival_2015_B_D();
    //cpsco_2019_session_1_E();
    //yukicoder_3017();
    //KUPC_2018_I();
}
accuracy: 1
time_ms: 180
memory_kb: 10780
final_rank: 11

code_snippet: //
// 区間 (と値) を Set で管理する構造体
//
// verified
//   第六回 アルゴリズム実技検定 M - 等しい数
//     https://atcoder.jp/contests/past202104-open/tasks/past202104_m
//
//   RUPC 2018 G - Elevator
//     https://onlinejudge.u-aizu.ac.jp/problems/2880 
//


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


#define COUT(x) cout << #x << " = " << (x) << " (L" << __LINE__ << ")" << endl

// debug stream
template<class T1, class T2> ostream& operator << (ostream &s, pair<T1,T2> P)
{ return s << '<' << P.first << ", " << P.second << '>'; }
template<class T> ostream& operator << (ostream &s, vector<T> P)
{ for (int i = 0; i < P.size(); ++i) { if (i > 0) { s << " "; } s << P[i]; } return s; }
template<class T> ostream& operator << (ostream &s, deque<T> P)
{ for (int i = 0; i < P.size(); ++i) { if (i > 0) { s << " "; } s << P[i]; } return s; }
template<class T> ostream& operator << (ostream &s, vector<vector<T> > P)
{ for (int i = 0; i < P.size(); ++i) { s << endl << P[i]; } return s << endl; }
template<class T> ostream& operator << (ostream &s, set<T> P)
{ for (auto it : P) { s << "<" << it << "> "; } return s; }
template<class T> ostream& operator << (ostream &s, multiset<T> P)
{ for (auto it : P) { s << "<" << it << "> "; } return s; }
template<class T1, class T2> ostream& operator << (ostream &s, map<T1,T2> P)
{ for (auto it : P) { s << "<" << it.first << "->" << it.second << "> "; } return s; }


// Interval Set
// T: type of range, VAL: data type
template<class T, class VAL = long long> struct IntervalSet {
    struct Node {
        T l, r;
        VAL val;
        Node(const T &l, const T &r, const VAL &val) : l(l), r(r), val(val) {}
        constexpr bool operator < (const Node &rhs) const {
            if (l != rhs.l) return l < rhs.l;
            else return r < rhs.r;
        }
    };

    // internal values
    const VAL identity;
    set<Node> S;

    // constructor
    IntervalSet(const VAL &identity = VAL()) : identity(identity) {}
    IntervalSet(const vector<VAL> &v, const VAL &identity = VAL()) : identity(identity) {
        vector<Node> vec;
        for (int l = 0; l < (int)v.size();) {
            int r = l;
            while (r < (int)v.size() && v[r] == v[l]) r++;
            vec.emplace_back(l, r, v[l]);
            l = r;
        }
        S = set<Node>(vec.begin(), vec.end());
    }

    // get the iterator of interval which contains p
    // not exist -> S.end()
    constexpr typename set<Node>::iterator get(const T &p) {
        auto it = S.upper_bound(Node(p, numeric_limits<T>::max(), 0));
        if (it == S.begin()) return S.end();
        it = prev(it);
        if (it->l <= p && p < it->r) return it;
        else return S.end();
    }

    // exist the interval which contains p: true
    constexpr bool contains(const T &p) {
        auto it = get(p);
        if (it != S.end()) return true;
        else return false;
    }

    // get the value of interval which contains p
    // not exist -> identity
    constexpr VAL get_val(const T &p) {
        auto it = get(p);
        if (it != S.end()) return it->val;
        else return identity;
    }
    VAL operator [] (const T &p) const {
        return get_val(p);
    }

    // get the leftist iterator of interval which contains value >= p
    constexpr typename set<Node>::iterator lower_bound(const T &p) {
        auto it = S.upper_bound(Node(p, numeric_limits<T>::max(), 0));
        if (it == S.begin()) return it;
        else return prev(it);
    }

    // is p, q in same interval?
    constexpr bool same(const T &p, const T &q) {
        if (!contains(p) || !contains(q)) return false;
        return get(p) == get(q);
    }

    // update [l, r] with value val
    // del: reflect effects of interval-delete
    // add: reflect effects of interval add
    template<class ADDFUNC, class DELFUNC> void update(T l, T r, const VAL &val, const ADDFUNC &add, const DELFUNC &del) {
        auto it = S.lower_bound(Node(l, 0, val));
        while (it != S.end() && it->l <= r) {
            if (it->l == r) {
                if (it->val ==val) {
                    del(r, it->r, val);
                    r = it->r;
                    it = S.erase(it);
                }
                break;
            }
            if (it->r <= r) {
                del(it->l, it->r, it->val);
                it = S.erase(it);
            } else {
                if (it->val == val) {
                    r = it->r;
                    del(it->l, it->r, it->val);
                    it = S.erase(it);
                } else {
                    del(it->l, r, it->val);
                    Node node = *it;
                    it = S.erase(it);
                    it = S.emplace_hint(it, r, node.r, node.val);
                }
            }
        }
        if (it != S.begin()) {
            it = prev(it);
            if (it->r == l) {
                if (it->val == val) {
                    del(it->l, it->r, it->val);
                    l = it->l;
                    it = S.erase(it);
                }
            } else if (l < it->r) {
                if (it->val == val) {
                    del(it->l, it->r, it->val);
                    l = min(l, it->l);
                    r = max(r, it->r);
                    it = S.erase(it);
                } else {
                    if (r < it->r) {
                        it = S.emplace_hint(next(it), r, it->r, it->val);
                        it = prev(it);
                    }
                    del(l, min(r, it->r), it->val);
                    Node node = *it;
                    it = S.erase(it);
                    it = S.emplace_hint(it, node.l, l, node.val);
                }
            }
        }
        if (it != S.end()) it = next(it);
        add(l, r, val);
        S.emplace_hint(it, l, r, val);
    }
    void update(const T &l, const T &r, const VAL &val) {
        update(l, r, val, [](T, T, VAL){}, [](T, T, VAL){});
    }
    template<class ADDFUNC, class DELFUNC> void update(T l, T r, const ADDFUNC &add, const DELFUNC &del) {
        update(l, r, VAL(), add, del);
    }
    void update(const T &l, const T &r) {
        update(l, r, VAL(), [](T, T, VAL){}, [](T, T, VAL){});
    }

    // remove
    template<class ADDFUNC, class DELFUNC> void remove(T l, T r, const ADDFUNC &add, const DELFUNC &del) {
        auto it = S.lower_bound(Node(l, 0, VAL()));
        while (it != S.end() && it->l <= r) {
            if (it->r <= r) {
                del(it->l, it->r, it->val);
                it = S.erase(it);
            } else {
                del(it->l, r, it->val);
                Node node = *it;
                it = S.erase(it);
                it = S.emplace_hint(it, r, node.r, node.val);
            }
        }
        if (it != S.begin()) {
            it = prev(it);
            if (l < it->r) {
                if (r < it->r) {
                    it = S.emplace_hint(next(it), r, it->r, it->val);
                    it = prev(it);
                }
                del(l, min(r, it->r), it->val);
                Node node = *it;
                it = S.erase(it);
                it = S.emplace_hint(it, node.l, l, node.val);
            }
        }
    }
    void remove(const T &l, const T &r) {
        remove(l, r, [](T, T, VAL){}, [](T, T, VAL){});
    }

    // debug
    friend ostream& operator << (ostream &s, const IntervalSet &ins) {
        for (auto e : ins.S) {
            s << "([" << e.l << ", " << e.r << "): " << e.val << ") ";
        }
        return s;
    }
};


//------------------------------//
// Examples
//------------------------------//

// 第六回 アルゴリズム実技検定 M - 等しい数
void PAST_6_M() {
    long long N, Q;
    cin >> N;
    vector<long long> A(N);
    map<long long, long long> cnt;
    for (int i = 0; i < N; i++) {
        cin >> A[i];
        cnt[A[i]]++;
    }
    long long res = 0;
    for (auto [val, num] : cnt) res += num * (num - 1) / 2;

    auto add = [&](int l, int r, long long val) -> void {
        long long before = cnt[val] * (cnt[val] - 1) / 2;
        cnt[val] += r - l;
        long long after = cnt[val] * (cnt[val] - 1) / 2;
        res += after - before;
    };
    auto del = [&](int l, int r, long long val) -> void {
        long long before = cnt[val] * (cnt[val] - 1) / 2;
        cnt[val] -= r - l;
        long long after = cnt[val] * (cnt[val] - 1) / 2;
        res += after - before;
    };
    IntervalSet<int, long long> ins(A);

    cin >> Q;
    while (Q--) {
        int l, r;
        long long val;
        cin >> l >> r >> val;
        l--;
        ins.update(l, r, val, add, del);
        cout << res << '\n';
    }
}

// RUPC 2018 G - Elevator
void RUPC_2018_G() {
    using fll = array<long long, 4>;
    int N, M, Q, t, l, r;
    cin >> N >> M >> Q;
    vector<fll> qs(M + Q);
    for (int i = 0; i < M; i++) {
        cin >> t >> l >> r, l--, r--;
        qs[i] = fll({-1, t*2+1, l*2, r*2+1});
    }
    for (int i = 0; i < Q; i++) {
        cin >> t >> l >> r, l--, r--;
        qs[i+M] = fll({i, t*2, l*2, r*2});
    }
    sort(qs.begin(), qs.end(), [&](const fll &p, const fll &q) { return p[1] < q[1]; });

    IntervalSet<long long> ins;
    vector<bool> res(Q, false);
    for (auto q : qs) {
        if (q[0] == -1) {
            ins.update(q[2], q[3]);
        } else {
            if (q[2] >= q[3] || ins.same(q[2], q[3])) res[q[0]] = true;
            else res[q[0]] = false;
        }
        //cout << "(" << q[0] << ", " << q[1] << ", " << q[2] << ", " << q[3] << "): " << ins << endl;
    }
    for (int q = 0; q < Q; ++q) cout << (res[q] ? "Yes" : "No") << endl;
}


int main() {
    //PAST_6_M();
    RUPC_2018_G();
}
accuracy: 1
time_ms: 180
memory_kb: 10948
final_rank: 12

code_snippet: #include <bits/stdc++.h>

#if __has_include(<atcoder/all>)
#include <atcoder/all>
std::istream &operator>>(std::istream &is, atcoder::modint &v) {
    long long value;
    is >> value;
    v = value;
    return is;
}
std::ostream &operator<<(std::ostream &os, const atcoder::modint &v) {
    os << v.val();
    return os;
}
std::ostream &operator<<(std::ostream &os, const atcoder::modint998244353 &v) {
    os << v.val();
    return os;
}
std::istream &operator>>(std::istream &is, atcoder::modint998244353 &v) {
    long long x;
    is >> x;
    v = x;
    return is;
}
std::ostream &operator<<(std::ostream &os, const atcoder::modint1000000007 &v) {
    os << v.val();
    return os;
}
std::istream &operator>>(std::istream &is, atcoder::modint1000000007 &v) {
    long long x;
    is >> x;
    v = x;
    return is;
}
#endif

using namespace std;
using ll = long long;
using pll = pair<ll, ll>;
#define newl '\n';
#define rep(i, s, t) for (ll i = s; i < (ll)(t); i++)
#define rrep(i, s, t) for (ll i = (ll)(t) - 1; i >= (ll)(s); i--)
#define all(x) begin(x), end(x)
#define eb emplace_back
#define pb push_back
#define TT template <typename T>
TT using vec = vector<T>;
TT using vvec = vec<vec<T>>;
TT using vvvec = vec<vvec<T>>;
TT using minheap = priority_queue<T, vector<T>, greater<T>>;
TT using maxheap = priority_queue<T>;
TT bool chmin(T &x, T y) { return x > y ? (x = y, true) : false; }
TT bool chmax(T &x, T y) { return x < y ? (x = y, true) : false; }
TT bool rng(T l, T x, T r) { return l <= x && x < r; }
TT T flr(T a, T b) {
    if (b < 0) a = -a, b = -b;
    return a >= 0 ? a / b : (a + 1) / b - 1;
}

TT T cil(T a, T b) {
    if (b < 0) a = -a, b = -b;
    return a > 0 ? (a - 1) / b + 1 : a / b;
}
TT T sqr(T x) { return x * x; }
struct io_setup {
    io_setup() {
        ios::sync_with_stdio(false);
        std::cin.tie(nullptr);
        cout << fixed << setprecision(15);
    }
} io_setup;

template <class T1, class T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &p) {
    os << p.first << " " << p.second;
    return os;
}

TT ostream &operator<<(ostream &os, const vec<T> &v) {
    for (size_t i = 0; i < v.size(); i++) {
        os << v[i] << (i + 1 != v.size() ? " " : "");
    }
    return os;
}

template <typename T, ll n>
ostream &operator<<(ostream &os, const array<T, n> &v) {
    for (size_t i = 0; i < n; i++) {
        os << v[i] << (i + 1 != n ? " " : "");
    }
    return os;
}

template <typename T> ostream &operator<<(ostream &os, const vvec<T> &v) {
    for (size_t i = 0; i < v.size(); i++) {
        os << v[i] << (i + 1 != v.size() ? "\n" : "");
    }
    return os;
}

TT istream &operator>>(istream &is, vec<T> &v) {
    for (size_t i = 0; i < v.size(); i++) {
        is >> v[i];
    }
    return is;
}

#if __has_include(<debug/debug.hpp>)
#include <debug/debug.hpp>
#else
#define dbg(...) true
#define DBG(...) true
#define OUT(...) true
#endif

template <typename T, bool merge_adju> struct rangeset : public std::map<T, T> {
    rangeset() {}
    auto get(T p) const {
        auto it = (*this).upper_bound(p);
        if (it == (*this).begin() || (--it)->second <= p) return (*this).end();
        return it;
    }

    //[l, r)
    void insert(T l, T r) {
        if (l == r) return;
        assert(l <= r);
        auto itl = (*this).upper_bound(l),
             itr = (*this).lower_bound(r + merge_adju);
        if (itl != (*this).begin() && (--itl)->second + merge_adju <= l) {
            ++itl;
        }

        if (itl != itr) {
            if (itl->first < l) l = itl->first;
            if (prev(itr)->second > r) r = prev(itr)->second;
            map<T, T>::erase(itl, itr);
        }
        (*this)[l] = r;
    }

    //[l, r)
    void erase(T l, T r) {
        if (l == r) return;
        assert(l <= r);
        auto itl = (*this).upper_bound(l), itr = (*this).lower_bound(r);
        if (itl != (*this).begin() && (--itl)->second <= l) {
            ++itl;
        }
        if (itl == itr) return;
        T tl = l, tr = r;
        if (itl->first < l) tl = itl->first;
        if (prev(itr)->second > r) tr = prev(itr)->second;
        map<T, T>::erase(itl, itr);
        if (tl < l) (*this)[tl] = l;
        if (tr > r) (*this)[r] = tr;
    }

    bool contains(T p) const { return get(p) != (*this).end(); }
    bool same(T a, T b) const {
        if (a > b) swap(a, b);

        auto it = get(a);
        if (it == (*this).end()) return false;
        return b < it->second;
    }

    template <typename TYPE, bool ME>
    friend ostream &operator<<(ostream &os, rangeset<TYPE, ME> const &rhs) {
        for (auto [l, r] : rhs) os << "[" << l << ", " << r << ")";
        return os;
    }
};

int main() {
    ll n, m, q;
    cin >> n >> m >> q;
    using P = array<ll, 4>;

    rangeset<ll, false> rs;
    vec<P> es;
    rep(i, 0, m) {
        ll d, a, b;
        cin >> d >> a >> b;
        a--;
        es.pb(P{d, 1, a, b});
    }

    rep(i, 0, q) {
        ll e, s, t;
        cin >> e >> s >> t;
        s--;
        es.pb(P{e, -i, s, t});
    }

    sort(all(es));
    vec<ll> ans(q);
    for (auto [d, type, a, b] : es) {
        if (type != 1) {
            ll id = -type;
            if(a >= b - 1) ans[id] = true;
            else ans[id] = rs.same(a, b - 1);
        } else {
            rs.insert(a, b);
        }
    }

    rep(i, 0, q) {
        if (ans[i]) {
            cout << "Yes" << newl;
        } else {
            cout << "No" << newl;
        }
    }
}
accuracy: 1
time_ms: 40
memory_kb: 13428
final_rank: 2

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

#ifdef LOCAL
#include <debug.hpp>
#else
#define debug(...)
#endif

template <class S, class T>
struct Intervals {
    static constexpr S INF = numeric_limits<S>::max() / 4;
    static constexpr S L = -INF, R = INF;
    // data[l] : 区間 [l, r) に割り当てられた値（r は次の区間の l）
    map<S, T> data;

    // 定義域を [L, R) とし，[L, R) = none_val で初期化
    Intervals(T none_val = -1) {
        data[L] = none_val;
        data[R] = none_val;
    }

    // [l, r) = v
    void set(S l, S r, T v = 1) {
        l = max(l, L), r = min(r, R);
        if (l >= r) return;
        auto it = data.upper_bound(l);
        auto pit = prev(it);
        T vR = pit->second;
        if (pit->first == l) {
            pit = data.erase(pit);
            pit = prev(pit);
        }
        T vL = pit->second;
        // 丸ごと上書きされる区間は削除
        while (it != data.end()) {
            if (it->first > r) break;
            vR = it->second;
            it = data.erase(it);
        }
        if (v != vR) data[r] = vR;
        if (v != vL) data[l] = v;
    }

    // a[i]
    T get_value(S i) {
        assert(L <= i && i < R);
        return prev(data.upper_bound(i))->second;
    }

    // i を含む値の等しい極大区間が [l, r) = v としたとき {l, r, v} を返す
    tuple<S, S, T> get(S i) {
        assert(L <= i && i < R);
        auto it = data.upper_bound(i);
        auto pit = prev(it);
        return {pit->first, it->first, pit->second};
    }

    // [l, r) を連長圧縮した結果を {左端, 右端, 値} のリストとして返す
    vector<tuple<S, S, T>> get_all(S l, S r) {
        l = max(l, L), r = min(r, R);
        if (l >= r) return vector<tuple<S, S, T>>();
        vector<tuple<S, S, T>> res;
        auto nit = data.upper_bound(l), it = prev(nit);
        T i = it->first;
        while (i < r) {
            T ni = nit->first;
            res.emplace_back(max(i, l), min(ni, r), it->second);
            i = ni;
            it = nit++;
        }
        return res;
    }
};

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(20);
    int N, M, Q;
    cin >> N >> M >> Q;
    // day, type, left, right, index
    vector<tuple<int, int, int, int, int>> query;
    for (int i = 0; i < M; i++) {
        int D, A, B;
        cin >> D >> A >> B;
        query.emplace_back(D, 1, A, B, -1);
    }
    for (int i = 0; i < Q; i++) {
        int E, S, T;
        cin >> E >> S >> T;
        query.emplace_back(E, 0, S, T, i);
    }
    sort(query.begin(), query.end());

    Intervals<int, int> I;
    vector<string> ans(Q);
    for (auto [day, type, left, right, index] : query) {
        if (type == 1) {
            // [left, right) を通行可能にする
            I.set(left, right);
        }
        if (type == 0) {
            if (left >= right) {
                ans[index] = "Yes";
            } else {
                // [left, right) が通行可能なら Yes
                auto [l, r, v] = I.get(left);
                if (v == 1 && l <= left && right <= r) {
                    ans[index] = "Yes";
                } else {
                    ans[index] = "No";
                }
            }
        }
    }

    for (int i = 0; i < Q; i++) cout << ans[i] << '\n';
}
accuracy: 1
time_ms: 60
memory_kb: 15292
final_rank: 7

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <iomanip>
#include <set>
#include <array>
using namespace std;
typedef long long ll;
// const ll INF64 = 1LL << 60;
const ll INF64 = ((1LL<<62)-(1LL<<31));  // 10^18より大きく、かつ2倍しても負にならない数
const int INF32 = 0x3FFFFFFF;  // =(2^30)-1 10^9より大きく、かつ2倍しても負にならない数
template<class T> inline bool chmin(T &a, T b) { if(a > b) { a = b; return true; } return false; }
template<class T> inline bool chmax(T &a, T b) { if(a < b) { a = b; return true; } return false; }
#define YesNo(T) cout << ((T) ? "Yes" : "No") << endl;  // T:bool

// AOJ
// https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp18Day1/problems/G
// または https://onlinejudge.u-aizu.ac.jp/challenges/sources/VPC/RUPC/2880

/*
 * 「区間をsetで管理」で解く。
 * 
 * クエリについて、スタートのS階からエレベータで行ける最大の階をX階として、X>=TならばYes.
 * エレベータで行ける区間をsetで管理していく。
 * 
 * エレベータの設置とクエリを1つのデータにまとめて管理する。
 *   {日付, kind, 階, 階}
 * とし、日付かつ日付が同じならクエリが先に来るようにソートする。
 */

/*
 * 区間をsetで管理する構造体 閉区間で表すことに注意
 * llとINF64を定義しておくこと
 * メインは(1)(2)で、問題によっては(3)以降を使う感じか
 * またはset構造体のsを直接操作する
 * [verify]ABC364-F, "CODE FESTIVAL 2015 予選B"-D
 * 
 * コンストラクタ : interval_set s; or interval_set s(l,r);  後者はl<=i<=rを満たす[i,i]を区間登録
 * (1)get(pos) : 値posが含まれる区間のイテレータを返す。該当区間がなければs.end()を返す。
 * (2)ins(l,r) : 閉区間[l,r]を区間に追加する。その際に重なる区間は統合される。戻り値は区間数。
 * (3)same(x,y) : x,yが同一区間か判定
 * (4)merge(pos) : 位置posを指定して、隣接した区間が両隣にあれば統合する
 *    例){1,3},{4,6},{7,9}でmerge(4);で呼び出すと{1,9}になる
 *    マス目を埋めていくような問題で使えるかも
 * (5-1)get2_next(pos) : 値posが区間に含まれていればそこを、無ければ次の区間のイテレータを返す
 * (5-2)get2_prev(pos) : 同じく手前の区間のイテレータを返す 手前が無ければ該当無しとしてendを返す
 */
struct interval_set {
	using pll = pair<ll, ll>;
	set<pll> s;
	interval_set() {}
	interval_set(ll st, ll ed) { init(st, ed); }
	// チェック無しでst<=i<=edを満たす[i,i]を区間登録
	void init(ll st, ll ed) {
		for(ll i = st; i <= ed; i++) {
			s.insert({i, i});
		}
	}
	// 値posが含まれる区間のイテレータを返す
	// 該当区間がなければs.end()を返す
	set<pll>::iterator get(ll pos) {
		if(s.size() == 0) return s.end();
		// upper_boundの1つ手前をチェック
		auto itr = s.upper_bound({pos, INF64});
		if(itr == s.begin()) return s.end();
		itr--;
		if(itr->first <= pos && pos <= itr->second) return itr;  // left<=pos<=right
		else return s.end();
	}
	// 値posが区間に含まれていればそこを、無ければ次の区間のイテレータを返す
	set<pll>::iterator get2_next(ll pos) {
		if(s.size() == 0) return s.end();
		auto itr = get(pos);
		if(itr != s.end()) return itr;  // 区間があればそこを返す
		else return s.upper_bound({pos, INF64});  // 無い場合、次のイテレータ
	}
	// get2_nextと同じく手前の区間のイテレータを返す 手前が無ければ該当無しとしてendを返す
	set<pll>::iterator get2_prev(ll pos) {
		if(s.size() == 0) return s.end();
		auto itr = get(pos);
		if(itr != s.end()) return itr;  // 区間があればそこを返す
		// 無い場合は手前のイテレータ ただしbeginなら該当無しとしてendを返す
		if( (itr = s.upper_bound({pos, INF64})) == s.begin()) return s.end();
		else return prev(itr);
	}
	// 閉区間[l,r]を区間に追加し、その際に重なる区間は統合する
	size_t ins(ll l, ll r) {
		ll st, ed;  // [l,r]を囲む区間[st,ed]
		auto itr = get(l);
		if(itr == s.end()) {  // lが区間に存在しない
			st = l;
			s.insert({st, st});  // 後述の実装を簡易にするため区間登録しておく
		}
		else st = itr->first;

		if( (itr = get(r)) == s.end()) ed = r;
		else ed = itr->second;

		// 先に重なる区間を消してから、統合された区間を登録
		itr = get(st);
		while(itr != s.end() && itr->first <= ed) {
			itr = s.erase(itr);
		}
		s.insert({st, ed});
		return s.size();
	}
	// x,yが同一区間か判定
	bool same(ll x, ll y) {
		auto itr = get(x);
		if(itr == s.end()) return false;  // xが区間に含まれていないならfalse
		return (itr->first <= y && y <= itr->second);  // yがxの区間内か
	}
	// 位置posを指定して、隣接した区間が両隣にあれば統合する
	// 例：{1,3},{4,6},{7,9} で merge(4); で呼び出せば {1,9} となる
	// マス目を埋めていくような問題で使えるかも
	// posが区間に含まれないときの動作は未定義
	void merge(ll pos) {
		auto itr = get(pos);
		auto nxt = next(itr);
		if(nxt != s.end()) {
			if(itr->second+1 == nxt->first) ins(itr->second, nxt->first);
		}
		itr = get(pos);
		if(itr != s.begin()) {
			auto prv = prev(itr);
			if(prv->second+1 == itr->first) ins(prv->second, itr->first);
		}
	}
	void debug(void) {
		// return;
		for(auto &e : s) {
			cout << "[" << e.first << "," << e.second << "], ";
		}
		cout << endl;
	}
};

int main(void)
{
	int i;
	int N, M, Q; cin >> N >> M >> Q;
	vector<array<int,4>> dt;  // {日付, kind, 階, 階}  日付が同じならクエリの方が先に来るようにする
	for(i = 0; i < M; i++)
	{
		int d, a, b; cin >> d >> a >> b;
		dt.push_back({d, INF32, a, b});
	}
	for(i = 0; i < Q; i++)
	{
		int e, s, t; cin >> e >> s >> t;
		dt.push_back({e, i, s, t});
	}
	sort(dt.begin(), dt.end());  // 日付でソート
	vector<int> ans(Q, 0);

	interval_set is(1, N);
	for(auto [d, k, a, b] : dt)
	{
		if(k == INF32)  // エレベーター設置
		{
			is.ins(a, b);
		}
		else  // クエリ a階->b階へ行けるか
		{
			auto itr = is.get(a);
			ans[k] = (itr->second >= b) ? 1 : 0;
		}
	}

	for(auto &e : ans) YesNo(e==1);

	return 0;
}
accuracy: 1
time_ms: 210
memory_kb: 13560
final_rank: 14

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <iomanip>
#include <set>
#include <array>
using namespace std;
typedef long long ll;
// const ll INF64 = 1LL << 60;
const ll INF64 = ((1LL<<62)-(1LL<<31));  // 10^18より大きく、かつ2倍しても負にならない数
const int INF32 = 0x3FFFFFFF;  // =(2^30)-1 10^9より大きく、かつ2倍しても負にならない数
template<class T> inline bool chmin(T &a, T b) { if(a > b) { a = b; return true; } return false; }
template<class T> inline bool chmax(T &a, T b) { if(a < b) { a = b; return true; } return false; }
#define YesNo(T) cout << ((T) ? "Yes" : "No") << endl;  // T:bool

// https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp18Day1/problems/G

/*
 * 
 * 
 * 今いる階から行ける区間
 * 区間最大より以下であれば、行ける
 * 
 * {日付、kind, 階、階}で登録、日付でソート
 */

/*
 * 区間をsetで管理する構造体 閉区間で表すことに注意
 * llとINF64を定義しておくこと
 * メインは(1)(2)で、問題によっては(3)以降を使う感じか
 * またはset構造体のsを直接操作する
 * [verify]ABC364-F, "CODE FESTIVAL 2015 予選B"-D
 * 
 * コンストラクタ : interval_set s; or interval_set s(l,r);  後者はl<=i<=rを満たす[i,i]を区間登録
 * (1)get(pos) : 値posが含まれる区間のイテレータを返す。該当区間がなければs.end()を返す。
 * (2)ins(l,r) : 閉区間[l,r]を区間に追加する。その際に重なる区間は統合される。戻り値は区間数。
 * (3)same(x,y) : x,yが同一区間か判定
 * (4)merge(pos) : 位置posを指定して、隣接した区間が両隣にあれば統合する
 *    例){1,3},{4,6},{7,9}でmerge(4);で呼び出すと{1,9}になる
 *    マス目を埋めていくような問題で使えるかも
 * (5-1)get2_next(pos) : 値posが区間に含まれていればそこを、無ければ次の区間のイテレータを返す
 * (5-2)get2_prev(pos) : 同じく手前の区間のイテレータを返す 手前が無ければ該当無しとしてendを返す
 */
struct interval_set {
	using pll = pair<ll, ll>;
	set<pll> s;
	interval_set() {}
	interval_set(ll st, ll ed) { init(st, ed); }
	// チェック無しでst<=i<=edを満たす[i,i]を区間登録
	void init(ll st, ll ed) {
		for(ll i = st; i <= ed; i++) {
			s.insert({i, i});
		}
	}
	// 値posが含まれる区間のイテレータを返す
	// 該当区間がなければs.end()を返す
	set<pll>::iterator get(ll pos) {
		if(s.size() == 0) return s.end();
		// upper_boundの1つ手前をチェック
		auto itr = s.upper_bound({pos, INF64});
		if(itr == s.begin()) return s.end();
		itr--;
		if(itr->first <= pos && pos <= itr->second) return itr;  // left<=pos<=right
		else return s.end();
	}
	// 値posが区間に含まれていればそこを、無ければ次の区間のイテレータを返す
	set<pll>::iterator get2_next(ll pos) {
		if(s.size() == 0) return s.end();
		auto itr = get(pos);
		if(itr != s.end()) return itr;  // 区間があればそこを返す
		else return s.upper_bound({pos, INF64});  // 無い場合、次のイテレータ
	}
	// get2_nextと同じく手前の区間のイテレータを返す 手前が無ければ該当無しとしてendを返す
	set<pll>::iterator get2_prev(ll pos) {
		if(s.size() == 0) return s.end();
		auto itr = get(pos);
		if(itr != s.end()) return itr;  // 区間があればそこを返す
		// 無い場合は手前のイテレータ ただしbeginなら該当無しとしてendを返す
		if( (itr = s.upper_bound({pos, INF64})) == s.begin()) return s.end();
		else return prev(itr);
	}
	// 閉区間[l,r]を区間に追加し、その際に重なる区間は統合する
	size_t ins(ll l, ll r) {
		ll st, ed;  // [l,r]を囲む区間[st,ed]
		auto itr = get(l);
		if(itr == s.end()) {  // lが区間に存在しない
			st = l;
			s.insert({st, st});  // 後述の実装を簡易にするため区間登録しておく
		}
		else st = itr->first;

		if( (itr = get(r)) == s.end()) ed = r;
		else ed = itr->second;

		// 先に重なる区間を消してから、統合された区間を登録
		itr = get(st);
		while(itr != s.end() && itr->first <= ed) {
			itr = s.erase(itr);
		}
		s.insert({st, ed});
		return s.size();
	}
	// x,yが同一区間か判定
	bool same(ll x, ll y) {
		auto itr = get(x);
		if(itr == s.end()) return false;  // xが区間に含まれていないならfalse
		return (itr->first <= y && y <= itr->second);  // yがxの区間内か
	}
	// 位置posを指定して、隣接した区間が両隣にあれば統合する
	// 例：{1,3},{4,6},{7,9} で merge(4); で呼び出せば {1,9} となる
	// マス目を埋めていくような問題で使えるかも
	// posが区間に含まれないときの動作は未定義
	void merge(ll pos) {
		auto itr = get(pos);
		auto nxt = next(itr);
		if(nxt != s.end()) {
			if(itr->second+1 == nxt->first) ins(itr->second, nxt->first);
		}
		itr = get(pos);
		if(itr != s.begin()) {
			auto prv = prev(itr);
			if(prv->second+1 == itr->first) ins(prv->second, itr->first);
		}
	}
	void debug(void) {
		// return;
		for(auto &e : s) {
			cout << "[" << e.first << "," << e.second << "], ";
		}
		cout << endl;
	}
};

int main(void)
{
	int i;
	int N, M, Q; cin >> N >> M >> Q;
	vector<array<int,4>> dt;  // {日付, kind, 階, 階}  日付が同じならクエリの方が先に来るようにする
	for(i = 0; i < M; i++)
	{
		int d, a, b; cin >> d >> a >> b;
		dt.push_back({d, INF32, a, b});
	}
	for(i = 0; i < Q; i++)
	{
		int e, s, t; cin >> e >> s >> t;
		dt.push_back({e, i, s, t});
	}
	sort(dt.begin(), dt.end());  // 日付でソート
	vector<int> ans(Q, 0);

	interval_set is(1, N);
	for(auto [d, k, a, b] : dt)
	{
		if(k == INF32)  // エレベーター設置
		{
			is.ins(a, b);

		}
		else  // クエリ a階->b階へ行けるか
		{
			auto itr = is.get(a);
			ans[k] = (itr->second >= b) ? 1 : 0;
		}
	}


	for(auto &e : ans) YesNo(e==1);

	return 0;
}
accuracy: 1
time_ms: 180
memory_kb: 13144
final_rank: 13

code_snippet: #include <bits/stdc++.h>
#define REP(i, n) for(int i = 0; i < (int)(n); ++i)
#define FOR(i, l, r) for(int i = (int)(l); i < (int)(r); ++i)
#define ALL(v) (v).begin(), (v).end()
using llong = long long;
using vi = std::vector<int>;
using vvi = std::vector<vi>;
using pii = std::pair<int, int>;
using namespace std;
constexpr int INF = 1e9;
constexpr long long LINF = 1e18;
constexpr double EPS = 1e-10;
constexpr int MOD = 998'244'353;
constexpr int MOD2 = 1e9 + 7;

template <typename Type>
inline std::istream &operator>>(std::istream &is, std::vector<Type> &v) {
    for(Type &in : v) is >> in;
    return is;
}

template <typename Type>
inline std::ostream &operator<<(std::ostream &os, const std::vector<Type> &v) {
    for(auto itr = v.cbegin(); itr != v.cend(); ++itr) os << (itr == v.cbegin() ? "" : " ") << *itr;
    return os;
}

#ifdef DEBUG

#include "lib/Utils/debug.hpp"
using namespace algorithm;

#else

#define debug(...) static_cast<void>(0)

#endif

// Integer Interval Set（整数の集合を区間で管理するデータ構造）.
template <typename T, typename std::enable_if_t<std::is_integral<T>::value, bool> = false>
class IntegerIntervalSet {
    std::set<std::pair<T, T> > m_st;  // m_st:=(整数の集合). 連続している区間[l,r)をpair(l,r)で表現する．

public:
    IntegerIntervalSet() {
        static_assert(min_limit() < max_limit());
        // 番兵を配置．
        m_st.emplace(min_limit() - 2, min_limit() - 1);
        m_st.emplace(max_limit() + 1, max_limit() + 2);
    }

    static constexpr T min_limit() { return std::numeric_limits<T>::min() + 2; }
    static constexpr T max_limit() { return std::numeric_limits<T>::max() - 2; }
    // 整数xを追加する．O(logN).
    bool insert(T x) { return insert(x, x + 1); }
    // 区間[l,r)の整数を追加する．O(logN).
    bool insert(T l, T r) {
        assert(min_limit() <= l and l < r and r <= max_limit());
        auto iter1 = std::prev(m_st.lower_bound(std::pair<T, T>(l + 1, l + 1)));
        auto [l1, r1] = *iter1;
        if(r <= r1) return false;  // 全て集合に含まれている場合．
        if(l <= r1) l = l1;
        else iter1++;
        auto iter3 = m_st.lower_bound(std::pair<T, T>(r, r));
        auto iter2 = std::prev(iter3);
        auto [l2, r2] = *iter2;
        auto [l3, r3] = *iter3;
        if(r == l3) {
            m_st.erase(iter1, ++iter3);
            m_st.emplace(l, r3);
        } else {
            m_st.erase(iter1, iter3);
            if(r <= r2) m_st.emplace(l, r2);
            else m_st.emplace(l, r);
        }
        return true;
    }
    // 整数xを削除する．O(logN).
    bool erase(T x) { return erase(x, x + 1); }
    // 区間[l,r)の整数を削除する．O(logN).
    bool erase(T l, T r) {
        assert(min_limit() <= l and l < r and r <= max_limit());
        auto iter1 = std::prev(m_st.lower_bound(std::pair<T, T>(l + 1, l + 1)));
        auto iter3 = m_st.lower_bound(std::pair<T, T>(r, r));
        auto iter2 = std::prev(iter3);
        auto [l1, r1] = *iter1;
        auto [l2, r2] = *iter2;
        if(l < r1) {
            m_st.erase(iter1, iter3);
            if(l1 < l) m_st.emplace(l1, l);
        } else {
            if(iter1 == iter2) return false;  // 全て集合に含まれていない場合．
            m_st.erase(++iter1, iter3);
        }
        if(r < r2) m_st.emplace(r, r2);
        return true;
    }
    // 整数xが集合に含まれているか判定する．O(logN).
    int contains(T x) const { return contains(x, x + 1); }
    // 区間[l,r)の整数が集合に含まれているか判定する．O(logN).
    int contains(T l, T r) const {
        assert(min_limit() <= l and l < r and r <= max_limit());
        const auto &[_, pr] = *std::prev(m_st.lower_bound(std::pair<T, T>(l + 1, l + 1)));
        if(pr <= l) return 0;  // 全て含まれていない場合．
        if(pr < r) return 1;   // 一部のみ含まれている場合．
        return 2;              // 全て含まれている場合．
    }
    // x以上の整数で集合に含まれない最小の値 (mex: Minimum EXcluded value) を求める．O(logN).
    T mex(T x) const {
        assert(min_limit() <= x and x < max_limit());
        const auto &[_, r] = *std::prev(m_st.lower_bound(std::pair<T, T>(x + 1, x + 1)));
        return (x < r ? r : x);
    }

    friend std::ostream &operator<<(std::ostream &os, const IntegerIntervalSet &ob) {
        os << "[";
        const int n = ob.m_st.size();
        int cnt = 0;
        for(auto iter = ob.m_st.cbegin(); iter != ob.m_st.cend(); ++iter) {
            if(0 < cnt and cnt < n - 1) {
                const auto &[l, r] = *iter;
                os << (cnt == 1 ? "" : " ") << "[" << l << ", " << r << ")";
            }
            cnt++;
        }
        os << "]";
        return os;
    }
};

int main() {
    int n;
    int m;
    int q;
    std::cin >> n >> m >> q;

    std::vector<std::tuple<int, int, int> > vt(m);
    for(auto &[d, a, b] : vt) std::cin >> d >> a >> b;
    std::sort(vt.begin(), vt.end());
    debug(vt);

    std::vector<std::tuple<int, int, int, int> > query(q);
    for(int i = 0; i < q; ++i) {
        auto &[e, s, t, idx] = query[i];
        std::cin >> e >> s >> t;
        idx = i;
    }
    std::sort(query.begin(), query.end());
    debug(query);

    std::vector<bool> ans(q);
    IntegerIntervalSet<int> st;
    int i = 0;
    for(const auto &[e, s, t, idx] : query) {
        while(i < m) {
            const auto &[d, a, b] = vt[i];
            if(e <= d) break;
            st.insert(a, b);
            i++;
        }
        debug(e, st);

        ans[idx] = (s >= t or st.contains(s, t) == 2);
    }

    for(auto elem : ans) std::cout << (elem ? "Yes" : "No") << "\n";
}
accuracy: 1
time_ms: 130
memory_kb: 7476
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll=long long;
using ull=unsigned long long;
using pll=pair<ll,ll>;
using tll=tuple<ll,ll,ll>;
using ld=long double;
const ll INF=(1ll<<60);
#define rep(i,n) for (ll i=0;i<(ll)(n);i++)
#define replr(i,l,r) for (ll i=(ll)(l);i<(ll)(r);i++)
#define all(v) v.begin(),v.end()
#define len(v) ((ll)v.size())
template<class T> inline bool chmin(T &a,T b){
    if(a>b){
        a=b;
        return true;
    }
    return false;
}
template<class T> inline bool chmax(T &a,T b){
    if(a<b){
        a=b;
        return true;
    }
    return false;
}
//[l,r)を管理(整数)
//番兵からはみ出すと壊れるので注意
//adjacent_mergeをTrueにすると[l,c)と[c,r)をマージする
//coverd_byはl==rのとき{T_INF,T_INF},l<rかつカバーされているときその区間,それ以外の時{-T_INF,-T_INF}を返す
//insert/eraseはそれぞれ増えた量/減った量を返す
//size,getは番兵を含まない

template<class T> struct interval_set{
    const T T_INF=numeric_limits<T>::max()/2;
    map<T,T> mp;
    T sum=0;
    bool adjacent_merge;
    interval_set(bool adjacent_merge_):sum(0),adjacent_merge(adjacent_merge_){
        mp[-T_INF]=-T_INF;
        mp[T_INF]=T_INF;
    }
    bool covered(T l,T r){  //[l,r)
        assert(l<=r);
        if(l==r) return true;
        auto itr=prev(mp.upper_bound(l));
        return itr->first<=l&&r<=itr->second;
    }
    bool covered(T x){
        return covered(x,x+1);
    }
    pair<T,T> covered_by(T l,T r){  //[l,r)
        assert(l<=r);
        if(l==r) return {T_INF,T_INF};
        auto itr=prev(mp.upper_bound(l));
        if(itr->first<=l&&r<=itr->second) return *itr;
        return {-T_INF,-T_INF};
    }
    pair<T,T> covered_by(T x){
        return covered_by(x,x+1);
    }
    bool same(T a,T b){
        auto [l,r]=covered_by(a);
        if(l==-T_INF) return false;
        return l<=b&&b<r;
    }
    T insert(T l,T r){  //[l,r)
        assert(l<=r);
        if(l==r) return 0;
        auto itrl=mp.lower_bound(l),itrr=mp.lower_bound(r+adjacent_merge);
        if(l<prev(itrl)->second+adjacent_merge) itrl--;
        l=min(l,itrl->first);
        r=max(r,prev(itrr)->second);
        T ret=r-l;
        for(auto itr=itrl;itr!=itrr;itr++) ret-=itr->second-itr->first;
        mp.erase(itrl,itrr);
        mp[l]=r;
        sum+=ret;
        return ret;
    }
    T insert(T x){
        return insert(x,x+1);
    }
    T erase(T l,T r){  //[l,r)
        assert(l<=r);
        if(l==r) return 0;
        auto itrl=mp.lower_bound(l),itrr=mp.lower_bound(r);
        if(l<prev(itrl)->second) itrl--;
        T x=min(l,itrl->first);
        T y=max(r,prev(itrr)->second);
        T ret=0;
        for(auto itr=itrl;itr!=itrr;itr++) ret+=itr->second-itr->first;
        mp.erase(itrl,itrr);
        if(x<l){
            mp[x]=l;
            ret-=l-x;
        }
        if(r<y){
            mp[r]=y;
            ret-=y-r;
        }
        sum-=ret;
        return ret;
    }
    T erase(T x){
        return erase(x,x+1);
    }
    inline int size(){
        return (int)mp.size()-2;
    }
    inline T get_sum(){
        return sum;
    }
    T mex(T x=0){
        auto itr=prev(mp.upper_bound(x));
        if(itr->first<=x&&x<itr->second) return itr->second;
        return x;
    }
    vector<pair<T,T>> get_comp(){
        vector<pair<T,T>> ret;
        for(auto [l,r]:mp){
            if(abs(l)==T_INF) continue;
            ret.emplace_back(l,r);
        }
        return ret;
    }
};
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    ll n,m,q;
    cin >> n >> m >> q;
    vector<pair<ll,tll>> vq;
    while(m--){
        ll d,a,b;
        cin >> d >> a >> b;
        vq.emplace_back(d,(tll){a,b,-1});
    }
    rep(i,q){
        ll e,s,t;
        cin >> e >> s >> t;
        vq.emplace_back(e,(tll){-s,-t,i});
    }
    vector<string> ans(q);
    interval_set<ll> st(false);
    sort(all(vq));
    for(auto [k,t]:vq){
        auto [x,y,i]=t;
        if(x<0){
            x=-x;
            y=-y;
            if(y<x||st.same(x,y)) ans[i]="Yes";
            else ans[i]="No";
        }else{
            y++;
            st.insert(x,y);
        }
    }
    rep(i,q) cout << ans[i] << '\n';
}
accuracy: 1
time_ms: 50
memory_kb: 14080
final_rank: 3

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll=long long;
using ull=unsigned long long;
using pll=pair<ll,ll>;
using tll=tuple<ll,ll,ll>;
using ld=long double;
const ll INF=(1ll<<60);
#define rep(i,n) for (ll i=0;i<(ll)(n);i++)
#define replr(i,l,r) for (ll i=(ll)(l);i<(ll)(r);i++)
#define all(v) v.begin(),v.end()
#define len(v) ((ll)v.size())
template<class T> inline bool chmin(T &a,T b){
    if(a>b){
        a=b;
        return true;
    }
    return false;
}
template<class T> inline bool chmax(T &a,T b){
    if(a<b){
        a=b;
        return true;
    }
    return false;
}
//[l,r)を管理(整数)
//番兵からはみ出すと壊れるので注意
//adjacent_mergeをTrueにすると[l,c)と[c,r)をマージする
//coverd_byはl==rのとき{T_INF,T_INF},l<rかつカバーされているときその区間,それ以外の時{-T_INF,-T_INF}を返す
//insert/eraseはそれぞれ増えた量/減った量を返す
//size,getは番兵を含まない

template<class T> struct interval_set{
    const T T_INF=numeric_limits<T>::max()/2;
    map<T,T> mp;
    bool adjacent_merge;
    interval_set(bool adjacent_merge_):adjacent_merge(adjacent_merge_){
        mp[-T_INF]=-T_INF;
        mp[T_INF]=T_INF;
    }
    bool covered(T l,T r){  //[l,r)
        assert(l<=r);
        if(l==r) return true;
        auto itr=prev(mp.upper_bound(l));
        return itr->first<=l&&r<=itr->second;
    }
    bool covered(T x){
        return covered(x,x+1);
    }
    pair<T,T> covered_by(T l,T r){  //[l,r)
        assert(l<=r);
        if(l==r) return {T_INF,T_INF};
        auto itr=prev(mp.upper_bound(l));
        if(itr->first<=l&&r<=itr->second) return *itr;
        return {-T_INF,-T_INF};
    }
    pair<T,T> covered_by(T x){
        return covered_by(x,x+1);
    }
    bool same(T a,T b){
        auto [l,r]=covered_by(a);
        if(l==-T_INF) return false;
        return l<=b&&b<r;
    }
    void insert(T l,T r){  //[l,r)
        assert(l<=r);
        if(l==r) return;
        auto itrl=mp.lower_bound(l),itrr=mp.lower_bound(r+adjacent_merge);
        if(l<prev(itrl)->second+adjacent_merge) itrl--;
        l=min(l,itrl->first);
        r=max(r,prev(itrr)->second);
        mp.erase(itrl,itrr);
        mp[l]=r;
    }
    void insert(T x){
        insert(x,x+1);
    }
    void erase(T l,T r){  //[l,r)
        assert(l<=r);
        if(l==r) return;
        auto itrl=mp.lower_bound(l),itrr=mp.lower_bound(r);
        if(l<prev(itrl)->second) itrl--;
        T x=min(l,itrl->first);
        T y=max(r,prev(itrr)->second);
        mp.erase(itrl,itrr);
        if(x<l) mp[x]=l;
        if(r<y) mp[r]=y;
    }
    void erase(T x){
        erase(x,x+1);
    }
    inline int size(){
        return (int)mp.size()-2;
    }
    T mex(T x=0){
        auto itr=prev(mp.upper_bound(x));
        if(itr->first<=x&&x<itr->second) return itr->second;
        return x;
    }
    vector<pair<T,T>> get(){
        vector<pair<T,T>> ret;
        for(auto [l,r]:mp){
            if(abs(l)==T_INF) continue;
            ret.emplace_back(l,r);
        }
        return ret;
    }
};
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    ll n,m,q;
    cin >> n >> m >> q;
    vector<pair<ll,tll>> vq;
    while(m--){
        ll d,a,b;
        cin >> d >> a >> b;
        vq.emplace_back(d,(tll){a,b,-1});
    }
    rep(i,q){
        ll e,s,t;
        cin >> e >> s >> t;
        vq.emplace_back(e,(tll){-s,-t,i});
    }
    vector<string> ans(q);
    interval_set<ll> st(false);
    sort(all(vq));
    for(auto [k,t]:vq){
        auto [x,y,i]=t;
        if(x<0){
            x=-x;
            y=-y;
            if(y<x||st.same(x,y)) ans[i]="Yes";
            else ans[i]="No";
        }else{
            y++;
            st.insert(x,y);
        }
    }
    rep(i,q) cout << ans[i] << '\n';
}
accuracy: 1
time_ms: 60
memory_kb: 15884
final_rank: 8

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll=long long;
using ull=unsigned long long;
using pll=pair<ll,ll>;
using tll=tuple<ll,ll,ll>;
using ld=long double;
const ll INF=(1ll<<60);
#define rep(i,n) for (ll i=0;i<(ll)(n);i++)
#define replr(i,l,r) for (ll i=(ll)(l);i<(ll)(r);i++)
#define all(v) v.begin(),v.end()
#define len(v) ((ll)v.size())
template<class T> inline bool chmin(T &a,T b){
    if(a>b){
        a=b;
        return true;
    }
    return false;
}
template<class T> inline bool chmax(T &a,T b){
    if(a<b){
        a=b;
        return true;
    }
    return false;
}
//[l,r)を管理(整数)
//番兵からはみ出すと壊れるので注意
//adjacent_mergeをTrueにすると[l,c)と[c,r)をマージする
//coverd_byはl==rのとき{T_INF,T_INF},l<rかつカバーされているときその区間,それ以外の時{-T_INF,-T_INF}を返す
//insert/eraseはそれぞれ増えた量/減った量を返す
//size,getは番兵を含まない

template<class T> struct interval_set{
    const T T_INF=numeric_limits<T>::max()/2;
    map<T,T> mp;
    bool adjacent_merge;
    interval_set(bool adjacent_merge_):adjacent_merge(adjacent_merge_){
        mp[-T_INF]=-T_INF;
        mp[T_INF]=T_INF;
    }
    bool covered(T l,T r){  //[l,r)
        assert(l<=r);
        if(l==r) return true;
        auto itr=prev(mp.upper_bound(l));
        return itr->first<=l&&r<=itr->second;
    }
    bool covered(T x){
        return covered(x,x+1);
    }
    pair<T,T> covered_by(T l,T r){  //[l,r)
        assert(l<=r);
        if(l==r) return {T_INF,T_INF};
        auto itr=prev(mp.upper_bound(l));
        if(itr->first<=l&&r<=itr->second) return *itr;
        return {-T_INF,-T_INF};
    }
    pair<T,T> covered_by(T x){
        return covered_by(x,x+1);
    }
    bool same(T a,T b){
        auto [l,r]=covered_by(a);
        if(l==-T_INF) return false;
        return l<=b&&b<r;
    }
    void insert(T l,T r){  //[l,r)
        assert(l<=r);
        if(l==r) return;
        auto itrl=mp.lower_bound(l),itrr=mp.lower_bound(r+adjacent_merge);
        if(l<prev(itrl)->second+adjacent_merge) itrl--;
        l=min(l,itrl->first);
        r=max(r,prev(itrr)->second);
        mp.erase(itrl,itrr);
        mp[l]=r;
    }
    void insert(T x){
        insert(x,x+1);
    }
    void erase(T l,T r){  //[l,r)
        assert(l<=r);
        if(l==r) return;
        auto itrl=mp.lower_bound(l),itrr=mp.lower_bound(r);
        if(l<prev(itrl)->second) itrl--;
        T x=min(l,itrl->first);
        T y=max(r,prev(itrr)->second);
        mp.erase(itrl,itrr);
        if(x<l) mp[x]=l;
        if(r<y) mp[r]=y;
    }
    void erase(T x){
        erase(x,x+1);
    }
    inline int size(){
        return (int)mp.size()-2;
    }
    T mex(T x=0){
        auto itr=prev(mp.upper_bound(x));
        if(itr->first<=x&&x<itr->second) return itr->second;
        return x;
    }
    vector<pair<T,T>> get(){
        vector<pair<T,T>> ret;
        for(auto [l,r]:mp){
            if(abs(l)==T_INF) continue;
            ret.emplace_back(l,r);
        }
        return ret;
    }
};
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    ll n,m,q;
    cin >> n >> m >> q;
    map<ll,vector<tll>> mp;
    while(m--){
        ll d,a,b;
        cin >> d >> a >> b;
        mp[d].emplace_back(a,b,-1);
    }
    rep(i,q){
        ll e,s,t;
        cin >> e >> s >> t;
        mp[e].emplace_back(-s,-t,i);
    }
    vector<string> ans(q);
    interval_set<ll> st(false);
    for(auto [k,v]:mp){
        sort(all(v));
        for(auto [x,y,i]:v){
            if(x<0){
                x=-x;
                y=-y;
                if(y<x||st.same(x,y)) ans[i]="Yes";
                else ans[i]="No";
            }else{
                y++;
                st.insert(x,y);
            }
        }
    }
    rep(i,q) cout << ans[i] << '\n';
}
accuracy: 1
time_ms: 130
memory_kb: 28164
final_rank: 17

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll=long long;
using ull=unsigned long long;
using pll=pair<ll,ll>;
using tll=tuple<ll,ll,ll>;
using ld=long double;
const ll INF=(1ll<<60);
#define rep(i,n) for (ll i=0;i<(ll)(n);i++)
#define replr(i,l,r) for (ll i=(ll)(l);i<(ll)(r);i++)
#define all(v) v.begin(),v.end()
#define len(v) ((ll)v.size())
template<class T> inline bool chmin(T &a,T b){
    if(a>b){
        a=b;
        return true;
    }
    return false;
}
template<class T> inline bool chmax(T &a,T b){
    if(a<b){
        a=b;
        return true;
    }
    return false;
}
//[l,r)を管理(整数)
//番兵からはみ出すと壊れるので注意
//adjacent_mergeをTrueにすると[l,c)と[c,r)をマージする
//coverd_byはl==rのとき{T_INF,T_INF},l<rかつカバーされているときその区間,それ以外の時{-T_INF,-T_INF}を返す
//insert/eraseはそれぞれ増えた量/減った量を返す
//size,getは番兵を含まない

template<class T> struct interval_set{
    const T T_INF=numeric_limits<T>::max()/2;
    map<T,T> mp;
    T sum=0;
    bool adjacent_merge;
    interval_set(bool adjacent_merge_):sum(0),adjacent_merge(adjacent_merge_){
        mp[-T_INF]=-T_INF;
        mp[T_INF]=T_INF;
    }
    bool covered(T l,T r){  //[l,r)
        assert(l<=r);
        if(l==r) return true;
        auto itr=prev(mp.upper_bound(l));
        return itr->first<=l&&r<=itr->second;
    }
    bool covered(T x){
        return covered(x,x+1);
    }
    pair<T,T> covered_by(T l,T r){  //[l,r)
        assert(l<=r);
        if(l==r) return {T_INF,T_INF};
        auto itr=prev(mp.upper_bound(l));
        if(itr->first<=l&&r<=itr->second) return *itr;
        return {-T_INF,-T_INF};
    }
    pair<T,T> covered_by(T x){
        return covered_by(x,x+1);
    }
    bool same(T a,T b){
        auto [l,r]=covered_by(a);
        if(l==-T_INF) return false;
        return l<=b&&b<r;
    }
    T insert(T l,T r){  //[l,r)
        assert(l<=r);
        if(l==r) return 0;
        auto itrl=mp.lower_bound(l),itrr=mp.lower_bound(r+adjacent_merge);
        if(l<prev(itrl)->second+adjacent_merge) itrl--;
        l=min(l,itrl->first);
        r=max(r,prev(itrr)->second);
        T ret=r-l;
        for(auto itr=itrl;itr!=itrr;itr++) ret-=itr->second-itr->first;
        mp.erase(itrl,itrr);
        mp[l]=r;
        sum+=ret;
        return ret;
    }
    T insert(T x){
        return insert(x,x+1);
    }
    T erase(T l,T r){  //[l,r)
        assert(l<=r);
        if(l==r) return 0;
        auto itrl=mp.lower_bound(l),itrr=mp.lower_bound(r);
        if(l<prev(itrl)->second) itrl--;
        T x=min(l,itrl->first);
        T y=max(r,prev(itrr)->second);
        T ret=0;
        for(auto itr=itrl;itr!=itrr;itr++) ret+=itr->second-itr->first;
        mp.erase(itrl,itrr);
        if(x<l){
            mp[x]=l;
            ret-=l-x;
        }
        if(r<y){
            mp[r]=y;
            ret-=y-r;
        }
        sum-=ret;
        return ret;
    }
    T erase(T x){
        return erase(x,x+1);
    }
    int size(){
        return (int)mp.size()-2;
    }
    inline T get_sum(){
        return sum;
    }
    T mex(T x=0){
        auto itr=prev(mp.upper_bound(x));
        if(itr->first<=x&&x<itr->second) return itr->second;
        return x;
    }
    vector<pair<T,T>> get(){
        vector<pair<T,T>> ret;
        for(auto [l,r]:mp){
            if(abs(l)==T_INF) continue;
            ret.emplace_back(l,r);
        }
        return ret;
    }
};
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    ll n,m,q;
    cin >> n >> m >> q;
    map<ll,vector<tll>> mp;
    while(m--){
        ll d,a,b;
        cin >> d >> a >> b;
        mp[d].emplace_back(a,b,-1);
    }
    rep(i,q){
        ll e,s,t;
        cin >> e >> s >> t;
        mp[e].emplace_back(-s,-t,i);
    }
    vector<string> ans(q);
    interval_set<ll> st(false);
    for(auto [k,v]:mp){
        sort(all(v));
        for(auto [x,y,i]:v){
            if(x<0){
                x=-x;
                y=-y;
                if(y<x||st.same(x,y)) ans[i]="Yes";
                else ans[i]="No";
            }else{
                y++;
                st.insert(x,y);
            }
        }
    }
    rep(i,q) cout << ans[i] << '\n';
}
accuracy: 1
time_ms: 130
memory_kb: 28164
final_rank: 17

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll=long long;
using ull=unsigned long long;
using pll=pair<ll,ll>;
using tll=tuple<ll,ll,ll>;
using ld=long double;
const ll INF=(1ll<<60);
#define rep(i,n) for (ll i=0;i<(ll)(n);i++)
#define replr(i,l,r) for (ll i=(ll)(l);i<(ll)(r);i++)
#define all(v) v.begin(),v.end()
#define len(v) ((ll)v.size())
template<class T> inline bool chmin(T &a,T b){
    if(a>b){
        a=b;
        return true;
    }
    return false;
}
template<class T> inline bool chmax(T &a,T b){
    if(a<b){
        a=b;
        return true;
    }
    return false;
}
//[l,r)を管理(整数)
//番兵からはみ出すと壊れるので注意
//adjacent_mergeをTrueにすると[l,c)と[c,r)をマージする
//coverd_byはl==rのとき{T_INF,T_INF},l<rかつカバーされているときその区間,それ以外の時{-T_INF,-T_INF}を返す
//insert/eraseはそれぞれ増えた量/減った量を返す
//size,getは番兵を含まない

template<class T> struct interval_set{
    const T T_INF=numeric_limits<T>::max()/2;
    map<T,T> mp;
    T sum=0;
    bool adjacent_merge;
    interval_set(bool adjacent_merge_):sum(0),adjacent_merge(adjacent_merge_){
        mp[-T_INF]=-T_INF;
        mp[T_INF]=T_INF;
    }
    bool covered(T l,T r){  //[l,r)
        assert(l<=r);
        if(l==r) return true;
        auto itr=prev(mp.upper_bound(l));
        return itr->first<=l&&r<=itr->second;
    }
    bool covered(T x){
        return covered(x,x+1);
    }
    pair<T,T> covered_by(T l,T r){  //[l,r)
        assert(l<=r);
        if(l==r) return {T_INF,T_INF};
        auto itr=prev(mp.upper_bound(l));
        if(itr->first<=l&&r<=itr->second) return *itr;
        return {-T_INF,-T_INF};
    }
    pair<T,T> covered_by(T x){
        return covered_by(x,x+1);
    }
    T insert(T l,T r){  //[l,r)
        assert(l<=r);
        if(l==r) return 0;
        auto itrl=mp.lower_bound(l),itrr=mp.lower_bound(r+adjacent_merge);
        if(l<prev(itrl)->second+adjacent_merge) itrl--;
        l=min(l,itrl->first);
        r=max(r,prev(itrr)->second);
        T ret=r-l;
        for(auto itr=itrl;itr!=itrr;itr++) ret-=itr->second-itr->first;
        mp.erase(itrl,itrr);
        mp[l]=r;
        sum+=ret;
        return ret;
    }
    T insert(T x){
        return insert(x,x+1);
    }
    T erase(T l,T r){  //[l,r)
        assert(l<=r);
        if(l==r) return 0;
        auto itrl=mp.lower_bound(l),itrr=mp.lower_bound(r);
        if(l<prev(itrl)->second) itrl--;
        T x=min(l,itrl->first);
        T y=max(r,prev(itrr)->second);
        T ret=0;
        for(auto itr=itrl;itr!=itrr;itr++) ret+=itr->second-itr->first;
        mp.erase(itrl,itrr);
        if(x<l){
            mp[x]=l;
            ret-=l-x;
        }
        if(r<y){
            mp[r]=y;
            ret-=y-r;
        }
        sum-=ret;
        return ret;
    }
    T erase(T x){
        return erase(x,x+1);
    }
    int size(){
        return (int)mp.size()-2;
    }
    inline T get_sum(){
        return sum;
    }
    T mex(T x=0){
        auto itr=prev(mp.upper_bound(x));
        if(itr->first<=x&&x<itr->second) return itr->second;
        return x;
    }
    vector<pair<T,T>> get(){
        vector<pair<T,T>> ret;
        for(auto [l,r]:mp){
            if(abs(l)==T_INF) continue;
            ret.emplace_back(l,r);
        }
        return ret;
    }
};
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    ll n,m,q;
    cin >> n >> m >> q;
    map<ll,vector<tll>> mp;
    while(m--){
        ll d,a,b;
        cin >> d >> a >> b;
        mp[d].emplace_back(a,b,-1);
    }
    rep(i,q){
        ll e,s,t;
        cin >> e >> s >> t;
        mp[e].emplace_back(-s,-t,i);
    }
    vector<string> ans(q);
    interval_set<ll> st(false);
    for(auto [k,v]:mp){
        sort(all(v));
        for(auto [x,y,i]:v){
            if(x<0){
                x=-x;
                y=-y;
                if(y<x||(st.covered(x)&&st.covered(y)&&st.covered_by(x)==st.covered_by(y))) ans[i]="Yes";
                else ans[i]="No";
            }else{
                y++;
                st.insert(x,y);
            }
        }
    }
    rep(i,q) cout << ans[i] << '\n';
}
accuracy: 1
time_ms: 140
memory_kb: 28172
final_rank: 19

code_snippet: #pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) { return (ull)rng() % B; }

struct UnionFind {
    vector<int> par, num;
    vector<int> l;
    UnionFind(int n) : par(n), num(n, 1), l(n) {
        iota(par.begin(), par.end(), 0); // include<numeric>
        l = par;
    }
    int find(int v) { return (par[v] == v) ? v : (par[v] = find(par[v])); }
    void unite(int u, int v) {
        u = find(u), v = find(v);
        if (u == v) return;
        if (num[u] < num[v]) swap(u, v);
        num[u] += num[v];
        l[u] = min(l[u], l[v]);
        par[v] = u;
    }
    bool same(int u, int v) { return find(u) == find(v); }
    int size(int v) { return num[find(v)]; }
    // [l,r]
    pair<int, int> kukan(int v) {
        v = find(v);
        return {l[v], l[v] + num[v] - 1};
    }
};

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n, m, q;
    cin >> n >> m >> q;
    vector<bool> res(q);
    vector<tuple<int, int, int, int>> v;
    for (int i = 0; i < m; ++i) {
        int d, a, b;
        cin >> d >> a >> b;
        v.push_back({d, 1e9, a - 1, b - 1});
    }
    for (int i = 0; i < q; ++i) {
        int e, s, t;
        cin >> e >> s >> t;
        v.push_back({e, i, s - 1, t - 1});
    }
    sort(v.begin(), v.end());
    UnionFind uf(n);
    for (auto [d, id, s, t] : v) {
        if (id == 1e9) {
            auto [l, r] = uf.kukan(s);
            for (int i = r + 1; i <= t; ++i) {
                uf.unite(s, i);
            }
        } else {
            res[id] = uf.same(s, t);
            if (s > t) res[id] = true;
        }
    }
    for (int i = 0; i < q; ++i) {
        if (res[i]) cout << "Yes\n";
        else cout << "No\n";
    }
}
accuracy: 1
time_ms: 40
memory_kb: 9288
final_rank: 1

code_snippet: #pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) { return (ull)rng() % B; }

struct UnionFind {
    vector<int> par, num;
    UnionFind(int n) : par(n), num(n, 1) {
        iota(par.begin(), par.end(), 0); // include<numeric>
    }
    int find(int v) { return (par[v] == v) ? v : (par[v] = find(par[v])); }
    void unite(int u, int v) {
        u = find(u), v = find(v);
        if (u == v) return;
        if (num[u] < num[v]) swap(u, v);
        num[u] += num[v];
        par[v] = u;
    }
    bool same(int u, int v) { return find(u) == find(v); }
    int size(int v) { return num[find(v)]; }
};

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n, m, q;
    cin >> n >> m >> q;
    vector<bool> res(q);
    vector<tuple<int, int, int, int>> v;
    for (int i = 0; i < m; ++i) {
        int d, a, b;
        cin >> d >> a >> b;
        if (a > b) swap(a, b);
        v.push_back({d, 1e9, a - 1, b - 1});
    }
    for (int i = 0; i < q; ++i) {
        int e, s, t;
        cin >> e >> s >> t;
        v.push_back({e, i, s - 1, t - 1});
    }
    sort(v.begin(), v.end());
    UnionFind uf(n);
    for (auto [d, id, s, t] : v) {
        if (id == 1e9) {
            for (int i = t; i >= s; --i) {
                if (uf.same(s, i)) break;
                uf.unite(s, i);
            }
        } else {
            res[id] = uf.same(s, t);
            if (s > t) res[id] = true;
        }
    }
    for (int i = 0; i < q; ++i) {
        if (res[i]) cout << "Yes\n";
        else cout << "No\n";
    }
}
accuracy: 0.2318840579710145
time_ms: 20
memory_kb: 5736
final_rank: 20

code_snippet: #define PROBLEM \
	"https://onlinejudge.u-aizu.ac.jp/problems/2880"

#include <bits/stdc++.h>

using namespace std;
#define SZ(x) (int) (x).size()
#define REP(i, n) for(int i = 0; i < (n); i++)
#define FOR(i, a, b) for(auto i = (a); i < (b); i++)
#define For(i, a, b, c) \
	for(auto i = (a); i != (b); i += (c))
#define REPR(i, n) for(auto i = (n) - 1; i >= 0; i--)
#define ALL(s) (s).begin(), (s).end()
#define so(V) sort(ALL(V))
#define rev(V) reverse(ALL(V))
#define uni(v) v.erase(unique(ALL(v)), (v).end())
#define eb emplace_back

typedef unsigned long long ull;
typedef long long ll;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<bool> vb;
typedef vector<vi> vvi;
typedef vector<vll> vvll;
typedef pair<int, int> PI;
typedef pair<ll, ll> PL;
const double EPS = 1e-6;
const int MOD = 1e9 + 7;
const int INF = (1 << 30);
const ll LINF = 1e18;
const double math_PI = acos(-1);

template<typename T>
vector<T> make_v(size_t a) {
	return vector<T>(a);
}

template<typename T, typename... Ts>
auto make_v(size_t a, Ts... ts) {
	return vector<decltype(make_v<T>(ts...))>(
		a, make_v<T>(ts...));
}

template<typename T, typename V>
typename enable_if<is_class<T>::value == 0>::type fill_v(
	T &t, const V &v) {
	t = v;
}

template<typename T, typename V>
typename enable_if<is_class<T>::value != 0>::type fill_v(
	T &t, const V &v) {
	for(auto &e: t) fill_v(e, v);
}

template<class T>
bool chmax(T &a, const T &b) {
	if(a < b) {
		a = b;
		return true;
	}
	return false;
}

template<class T>
bool chmin(T &a, const T &b) {
	if(a > b) {
		a = b;
		return true;
	}
	return false;
}

template<typename S, typename T>
istream &operator>>(istream &is, pair<S, T> &p) {
	cin >> p.first >> p.second;
	return is;
}

template<typename T>
istream &operator>>(istream &is, vector<T> &vec) {
	for(T &x: vec) is >> x;
	return is;
}

template<typename T>
string join(vector<T> &vec, string splitter) {
	stringstream ss;
	REP(i, SZ(vec)) {
		if(i != 0) ss << splitter;
		ss << vec[i];
	}
	return ss.str();
}

template<typename T>
ostream &operator<<(ostream &os, vector<T> &vec) {
	os << join(vec, " ");
	return os;
}

#ifdef LOCAL
#include "./cpp-dump/dump.hpp"
#include "./cpp-dump/mytypes.hpp"
#define dump(...) cpp_dump(__VA_ARGS__)
namespace cp = cpp_dump;
#else
#define dump(...)
#define preprocess(...)
#define CPP_DUMP_SET_OPTION(...)
#define CPP_DUMP_DEFINE_EXPORT_OBJECT(...)
#define CPP_DUMP_DEFINE_EXPORT_ENUM(...)
#define CPP_DUMP_DEFINE_DANGEROUS_EXPORT_OBJECT(...)
#endif
template<typename T = ll>
struct Range {
private:
	pair<T, T> P;
	pair<bool, bool> bound;
	pair<bool, bool> inclusive;
	int _id = -1;

public:
	Range() {
	}
	Range& left() {
		bound.first = false;
		inclusive.first = false;
		return *this;
	}
	Range& right() {
		bound.second = false;
		inclusive.second = false;
		return *this;
	}
	Range& left(T x, bool inclusive = true) {
		P.first = x;
		this->bound.first = true;
		this->inclusive.first = inclusive;
		return *this;
	}
	Range& right(T x, bool inclusive = true) {
		P.second = x;
		this->bound.second = true;
		this->inclusive.second = inclusive;
		return *this;
	}
	Range& id(int id) {
		this->_id = id;
		return *this;
	}
	int getId() const {
		return _id;
	}
	optional<T> getLeft() const {
		if(!bound.first) return nullopt;
		return P.first;
	}
	optional<T> getRight() const {
		if(!bound.second) return nullopt;
		return P.second;
	}
	bool isLeftInclusive() const {
		return inclusive.first;
	}
	bool isRightInclusive() const {
		return inclusive.second;
	}
	bool isLeftBound() const {
		return bound.first;
	}
	bool isRightBound() const {
		return bound.second;
	}

	int compareLeft(const Range<T>& r) const {
		if(bound.first && !r.bound.first) return -1;
		if(!bound.first && r.bound.first) return 1;
		if(!bound.first && !r.bound.first) return 0;
		if(P.first < r.P.first) return 1;
		if(P.first > r.P.first) return -1;
		if(inclusive.first && !r.inclusive.first) return 1;
		if(!inclusive.first && r.inclusive.first) return -1;
		return 0;
	}

	int compareRight(const Range<T>& r) const {
		if(bound.second && !r.bound.second) return 1;
		if(!bound.second && r.bound.second) return -1;
		if(!bound.second && !r.bound.second) return 0;
		if(P.second < r.P.second) return 1;
		if(P.second > r.P.second) return -1;
		if(inclusive.second && !r.inclusive.second)
			return -1;
		if(!inclusive.second && r.inclusive.second)
			return 1;
		return 0;
	}
	bool operator<(const Range<T>& r) const {
		int leftcmp = compareLeft(r);
		int rightcmp = compareRight(r);
		if(leftcmp == 1) return true;
		if(leftcmp == -1) return false;
		if(rightcmp == 1) return true;
		if(rightcmp == -1) return false;
		return false;
	}

	bool cross(const Range<T>& r) const {
		Range<T> a = *this;
		Range<T> b = r;
		if(a.compareLeft(b) == -1) swap(a, b);
		auto ra = a.getRight();
		auto lb = b.getLeft();
		if((!ra) || (!lb)) return true;
		return ra.value() > lb.value();
	}

	bool contact(const Range<T>& r) const {
		Range<T> a = *this;
		Range<T> b = r;
		if(a.compareLeft(b) == -1) swap(a, b);
		auto ra = a.getRight();
		auto lb = b.getLeft();
		if((!ra) || (!lb)) return true;
		return ra.value() > lb.value()
			|| ((a.isRightInclusive()
				 || b.isLeftInclusive())
				&& ra.value() == lb.value());
	}

	bool contains(const Range<T>& r) const {
		int leftcmp = compareLeft(r);
		int rightcmp = compareRight(r);
		return leftcmp != -1 && rightcmp != 1;
	}

	bool contained(const Range<T>& r) const {
		return r.contains(this);
	}

	void extendLeft(const Range<T>& r) {
		if(compareLeft(r) == -1) {
			auto ret = r.getLeft();
			if(!ret)
				left();
			else
				left(ret.value(), r.isLeftInclusive());
		}
	}

	void extendRight(const Range<T>& r) {
		if(compareRight(r) == 1) {
			auto ret = r.getRight();
			if(!ret)
				right();
			else
				right(ret.value(), r.isRightInclusive());
		}
	}

	T countIntegerPoint() const {
		if(!bound.first || !bound.second) return 0;
		T ret = P.second - P.first - 1;
		if(inclusive.first) ret++;
		if(inclusive.second) ret++;
		return max(T(0), ret);
	}

	T countMiddlePoint() const {
		if(!bound.first || !bound.second) return 0;
		return max(T(0), P.second - P.first);
	}

	Range<T> intersect(const Range<T>& r) const {
		auto ret = r;
		if(compareLeft(r) == -1)
			ret.left(P.first, inclusive.first);
		if(compareRight(r) == 1)
			ret.right(P.second, inclusive.second);
		return ret;
	}

	bool empty() const {
		auto l = getLeft();
		auto r = getRight();
		if(!l || !r) return false;
		return l.value() == r.value()
			&& (!isLeftInclusive() || !isRightInclusive());
	}

	bool operator==(const Range<T>& r) const {
		return compareLeft(r) == 0 && compareRight(r) == 0;
	}
};

template<typename T = ll>
struct RangeSet {
private:
	set<Range<T>> ranges;

public:
	RangeSet() {
	}

	optional<Range<T>> add(Range<T> r) {
		if(contains(r) || r.empty()) return nullopt;
		auto it = ranges.lower_bound(r);
		if(it != ranges.begin()) {
			it--;
			if(it->contact(r)) {
				r.extendLeft(*it);
				ranges.erase(it);
			}
		}
		vector<Range<T>> to_erase;
		it = ranges.lower_bound(r);
		while(true) {
			if(it == ranges.end()) break;
			if(!r.contact(*it)) break;
			r.extendRight(*it);
			to_erase.push_back(*it);
			it++;
		}
		for(auto &e: to_erase) ranges.erase(e);
		ranges.insert(r);
		return r;
	}

	void remove(Range<T> r) {
		typename decltype(ranges)::iterator it
			= ranges.lower_bound(r);
		vector<Range<T>> to_erase;
		vector<Range<T>> to_insert;
		if(it != ranges.begin()) {
			it--;
			auto xa = r.getLeft();
			auto xb = it->getRight();
			if(it->contains(r)) {
				to_erase.push_back(*it);
				Range<T> tmp = *it;
				auto ret = r.getLeft();
				if(ret) {
					tmp.right(ret.value(),
							  !r.isLeftInclusive());
				}
				if(!tmp.empty()) to_insert.push_back(tmp);
				tmp = *it;
				ret = r.getRight();
				if(ret) {
					tmp.left(ret.value(),
							 !r.isRightInclusive());
				}
				if(!tmp.empty()) to_insert.push_back(tmp);
			} else if(!xa) {
				to_erase.push_back(*it);
			} else {
				if(!xb || xa.value() < xb.value()) {
					to_erase.push_back(*it);
					Range<T> tmp = *it;
					tmp.right(xa.value(),
							  !r.isLeftInclusive());
					if(!tmp.empty())
						to_insert.push_back(tmp);
				} else if(xa.value() == xb.value()
						  && r.isLeftInclusive()
						  && it->isRightInclusive()) {
					to_erase.push_back(*it);
					Range<T> tmp = *it;
					tmp.right(xb.value(), false);
					if(!tmp.empty())
						to_insert.push_back(tmp);
				}
			}
		}
		it = ranges.lower_bound(r);
		while(true) {
			if(it == ranges.end()) break;
			if(!r.contact(*it)) break;
			if(r.contains(*it))
				to_erase.push_back(*it);
			else {
				to_erase.push_back(*it);
				auto rb = r.getRight();
				if(rb) {
					Range<T> tmp = *it;
					tmp.left(rb.value(),
							 !r.isRightInclusive());
					if(!tmp.empty())
						to_insert.push_back(tmp);
				}
			}
			it++;
		}
		for(auto &e: to_erase) ranges.erase(e);
		for(auto &e: to_insert) ranges.insert(e);
	}

	optional<Range<T>> getLeft(Range<T> r) const {
		auto it = ranges.lower_bound(r);
		if(it != ranges.begin()) {
			it--;
			return *it;
		}
		return nullopt;
	}

	optional<Range<T>> getRight(Range<T> r) const {
		auto it = ranges.upper_bound(r);
		if(it != ranges.end()) {
			return *it;
		}
		return nullopt;
	}

	optional<Range<T>> get(T x) const {
		auto r = Range<T>().left(x, true).right(x, true);
		auto it = ranges.lower_bound(r);
		if(it != ranges.end()) {
			if(it->contains(r)) return *it;
		}
		if(it != ranges.begin()) {
			it--;
			if(it->contains(r)) return *it;
		}
		return nullopt;
	}

	set<Range<T>> all() const {
		return ranges;
	}

	bool contains(Range<T> r) const {
		auto it = ranges.lower_bound(r);
		if(it != ranges.end()) {
			if(it->contains(r)) return true;
		}
		if(it != ranges.begin()) {
			it--;
			if(it->contains(r)) return true;
		}
		return false;
	}

	vi getContainsRangeId(Range<T> r) const {
		vi ret;
		auto it = ranges.lower_bound(r);
		if(it != ranges.begin()) {
			it--;
			if(r.contains(*it)) ret.push_back(it->getId());
			it++;
		}
		while(true) {
			if(it == ranges.end()) break;
			if(!r.contains(*it)) break;
			ret.push_back(it->getId());
			it++;
		}
		return ret;
	}

	int getContainedRangeId(Range<T> r) const {
		auto it = ranges.lower_bound(r);
		if(it != ranges.end()) {
			if(it->contains(r)) return it->getId();
		}
		if(it != ranges.begin()) {
			it--;
			if(it->contains(r)) return it->getId();
		}
		return false;
	}

	vi getCrossRangeId(Range<T> r) const {
		vi ret;
		auto it = ranges.lower_bound(r);
		if(it != ranges.begin()) {
			it--;
			if(it->cross(r)) ret.push_back(it->getId());
			it++;
		}
		while(true) {
			if(it == ranges.end()) break;
			if(!r.cross(*it)) break;
			ret.push_back(it->getId());
			it++;
		}
		return ret;
	}

	vi getContactRangeId(Range<T> r) const {
		vi ret;
		auto it = ranges.lower_bound(r);
		if(it != ranges.begin()) {
			it--;
			if(it->contact(r)) ret.push_back(it->getId());
			it++;
		}
		while(true) {
			if(it == ranges.end()) break;
			if(!r.contact(*it)) break;
			ret.push_back(it->getId());
			it++;
		}
		return ret;
	}

	bool contains(T x) const {
		auto r = Range<T>().left(x, true).right(x, true);
		return contains(r);
	}

	vi getContainsRangeId(T x) const {
		auto r = Range<T>().left(x, true).right(x, true);
		return getContainsRangeId(r);
	}

	int getContainedRangeId(T x) const {
		auto r = Range<T>().left(x, true).right(x, true);
		return getContainedRangeId(r);
	}

	vi getCrossRangeId(T x) const {
		auto r = Range<T>().left(x, true).right(x, true);
		return getCrossRangeId(r);
	}

	vi getContactRangeId(T x) const {
		auto r = Range<T>().left(x, true).right(x, true);
		return getContactRangeId(r);
	}

	T countIntegerPoint(Range<T> r) const {
		auto it = ranges.lower_bound(r);
		T ret = 0;
		if(it != ranges.begin()) {
			it--;
			if(it->contact(r)) {
				auto R = r.intersect(*it);
				ret += R.countIntegerPoint();
			}
			it++;
		}
		while(true) {
			if(it == ranges.end()) break;
			if(!r.contact(*it)) break;
			auto R = r.intersect(*it);
			ret += R.countIntegerPoint();
			it++;
		}
		return ret;
	}

	T countMiddlePoint(Range<T> r) const {
		auto it = ranges.lower_bound(r);
		T ret = 0;
		if(it != ranges.begin()) {
			it--;
			if(it->contact(r)) {
				auto R = r.intersect(*it);
				ret += R.countMiddlePoint();
			}
			it++;
		}
		while(true) {
			if(it == ranges.end()) break;
			if(!r.contact(*it)) break;
			auto R = r.intersect(*it);
			ret += R.countMiddlePoint();
			it++;
		}
		return ret;
	}

	optional<T> mex(T x) const {
		auto R = get(x);
		if(!R) return x;
		auto ret = R.value().getRight();
		if(!ret) return nullopt;
		int ans = ret.value();
		if(R.value().isRightInclusive()) ans++;
		return ans;
	}

	bool same(T x, T y) const {
		return contains(
			Range<T>().left(x, true).right(y, true));
	}
};


int main() {
	int N, M, Q;
	cin >> N >> M >> Q;
	RangeSet<ll> rs;
	using T = tuple<int, int, int>;
	priority_queue<T, vector<T>, greater<>> PQ;
	REP(i, M) {
		int D, A, B;
		cin >> D >> A >> B;
		PQ.push({ D, A, B });
	}
	using TT = tuple<int, int, int, int>;
	vector<TT> q;
	REP(i, Q) {
		int E, S, T;
		cin >> E >> S >> T;
		q.eb(E, S, T, i);
	}
	so(q);
	vb ans(Q);
	for(auto [e, s, t, i]: q) {
		while(!PQ.empty() && get<0>(PQ.top()) < e) {
			auto [d, a, b] = PQ.top();
			PQ.pop();
			rs.add(Range<>().left(a).right(b, true));
		}
		dump(e, s, t, i);
		dump(rs);
		if(rs.contains(Range<>().left(s).right(t, true))) {
			ans[i] = true;
		}
		if(s >= t) {
			ans[i] = true;
		}
	}
	REP(i, Q) {
		cout << (ans[i] ? "Yes" : "No") << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 190
memory_kb: 8468
final_rank: 9

code_snippet: #line 1 "test/aoj/2880.test.cpp"
#define PROBLEM "https://onlinejudge.u-aizu.ac.jp/problems/2880"
#include <algorithm>
#include <iostream>
#include <vector>

#line 2 "datastructure/range_set.hpp"

#include <map>
template <typename T>
struct range_set {
public:
    range_set(bool merge_adjacent = true) : _merge_adjacent(merge_adjacent) {
    }
    typename std::map<T, T>::const_iterator get(T p) const {
        auto it = ranges.upper_bound(p);
        if (it == ranges.begin()) return ranges.end();
        if (std::prev(it)->second < p) return ranges.end();
        return std::prev(it);
    }
    typename std::map<T, T>::const_iterator get(T l, T r) const {
        auto it = get(l);
        if (it == ranges.end()) return ranges.end();
        if (it->second < r) return ranges.end();
        return it;
    }
    void insert(T l, T r) {
        insert(l, r, [](T, T) {}, [](T, T) {});
    }
    template <class op_insert, class op_erase>
    void insert(T l, T r, const op_insert &f, const op_erase &g) {
        auto it_l = ranges.upper_bound(l);
        auto it_r = ranges.upper_bound(r + T(_merge_adjacent));
        if (it_l != ranges.begin() &&
            l - T(_merge_adjacent) <= std::prev(it_l)->second) {
            it_l--;
        }
        for (auto it = it_l; it != it_r; it = ranges.erase(it)) {
            l = std::min(l, it->first);
            r = std::max(r, it->second);
            g(it->first, it->second);
        }
        ranges[l] = r;
        f(l, r);
    }
    void erase(T l, T r) {
        erase(l, r, [](T, T) {}, [](T, T) {});
    }
    template <class op_insert, class op_erase>
    void erase(T l, T r, const op_insert &f, const op_erase &g) {
        auto it_l = ranges.upper_bound(l);
        auto it_r = ranges.upper_bound(r);
        if (it_l != ranges.begin() && l <= std::prev(it_l)->second) {
            it_l--;
        }
        for (auto it = it_l; it != it_r; it = ranges.erase(it)) {
            g(it->first, it->second);
        }
        T nl = std::min(l, it_l->first);
        T nr = std::max(r, std::prev(it_r)->second);
        if (nl < l) {
            ranges[nl] = l - 1;
            f(nl, l - 1);
        }
        if (r < nr) {
            ranges[r + 1] = nr;
            f(r + 1, nr);
        }
    }
    typename std::map<T, T>::const_iterator begin() const {
        return ranges.begin();
    }
    typename std::map<T, T>::const_iterator end() const {
        return ranges.end();
    }

private:
    std::map<T, T> ranges;
    bool _merge_adjacent;
};
#line 7 "test/aoj/2880.test.cpp"
int main() {
    int n, m, q;
    std::cin >> n >> m >> q;
    struct Q {
        int day, id, l, r;
    };
    std::vector<Q> query(m + q);
    for (int i = 0; i < m + q; i++) {
        int d, a, b;
        std::cin >> d >> a >> b;
        query[i] = {d, i, a, b};
    }
    std::sort(query.begin(), query.end(), [](Q a, Q b) {
        if (a.day == b.day) return a.id > b.id;
        return a.day < b.day;
    });
    range_set<int> st(false);
    std::vector<bool> ans(q);
    for (auto [_, id, l, r] : query) {
        if (id < m) {
            st.insert(l, r);
        } else {
            if (l < r) {
                ans[id - m] = st.get(l, r) != st.end();
            } else {
                ans[id - m] = true;
            }
        }
    }
    for (int i = 0; i < q; i++) {
        if (ans[i]) {
            std::cout << "Yes\n";
        } else {
            std::cout << "No\n";
        }
    }
}
accuracy: 1
time_ms: 120
memory_kb: 7692
final_rank: 5

code_snippet: #line 1 "test/aoj/2880.test.cpp"
#define PROBLEM "https://onlinejudge.u-aizu.ac.jp/problems/2880"
#include <algorithm>
#include <iostream>
#include <vector>

#line 2 "datastructure/range_set.hpp"

#include <map>
template <typename T>
struct range_set {
public:
    range_set(bool merge_adjacent = true) : _merge_adjacent(merge_adjacent) {
    }
    typename std::map<T, T>::const_iterator get(T p) const {
        auto it = ranges.upper_bound(p);
        if (it == ranges.begin()) return ranges.end();
        if (std::prev(it)->second < p) return ranges.end();
        return std::prev(it);
    }
    void insert(T l, T r) {
        insert(l, r, [](T, T) {}, [](T, T) {});
    }
    template <class op_insert, class op_erase>
    void insert(T l, T r, const op_insert &f, const op_erase &g) {
        auto it_l = ranges.upper_bound(l);
        auto it_r = ranges.upper_bound(r + T(_merge_adjacent));
        if (it_l != ranges.begin() &&
            l - T(_merge_adjacent) <= std::prev(it_l)->second) {
            it_l--;
        }
        for (auto it = it_l; it != it_r; it = ranges.erase(it)) {
            l = std::min(l, it->first);
            r = std::max(r, it->second);
            g(it->first, it->second);
        }
        ranges[l] = r;
        f(l, r);
    }
    void erase(T l, T r) {
        erase(l, r, [](T, T) {}, [](T, T) {});
    }
    template <class op_insert, class op_erase>
    void erase(T l, T r, const op_insert &f, const op_erase &g) {
        auto it_l = ranges.upper_bound(l);
        auto it_r = ranges.upper_bound(r);
        if (it_l != ranges.begin() && l <= std::prev(it_l)->second) {
            it_l--;
        }
        for (auto it = it_l; it != it_r; it = ranges.erase(it)) {
            g(it->first, it->second);
        }
        T nl = std::min(l, it_l->first);
        T nr = std::max(r, std::prev(it_r)->second);
        if (nl < l) {
            ranges[nl] = l - 1;
            f(nl, l - 1);
        }
        if (r < nr) {
            ranges[r + 1] = nr;
            f(r + 1, nr);
        }
    }
    typename std::map<T, T>::const_iterator begin() const {
        return ranges.begin();
    }
    typename std::map<T, T>::const_iterator end() const {
        return ranges.end();
    }

private:
    std::map<T, T> ranges;
    bool _merge_adjacent;
};
#line 7 "test/aoj/2880.test.cpp"
int main() {
    int n, m, q;
    std::cin >> n >> m >> q;
    struct Q {
        int day, id, l, r;
    };
    std::vector<Q> query(m + q);
    for (int i = 0; i < m + q; i++) {
        int d, a, b;
        std::cin >> d >> a >> b;
        query[i] = {d, i, a, b};
    }
    std::sort(query.begin(), query.end(), [](Q a, Q b) {
        if (a.day == b.day) return a.id > b.id;
        return a.day < b.day;
    });
    range_set<int> st(false);
    std::vector<bool> ans(q);
    for (auto [_, id, l, r] : query) {
        if (id < m) {
            st.insert(l, r);
        } else {
            if (l < r) {
                auto it_l = st.get(l);
                auto it_r = st.get(r);
                ans[id - m] = it_l != st.end() && it_l == it_r;
            } else {
                ans[id - m] = true;
            }
        }
    }
    for (int i = 0; i < q; i++) {
        if (ans[i]) {
            std::cout << "Yes\n";
        } else {
            std::cout << "No\n";
        }
    }
}
accuracy: 1
time_ms: 120
memory_kb: 7684
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;

#define ll long long

#define rep(i, n) for (ll i = 0; i < n; ++i)
#define all(v) begin(v), end(v)
// #define BIT(n) (1LL << (n))
#define MAX(type) numeric_limits<type>::max()
#define MIN(type) numeric_limits<type>::min()
#define yes cout << "Yes" << endl
#define no cout << "No" << endl
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
template <class T> using vec = vector<T>;

#line 2 "datastructure/lazy-segment-tree.hpp"

#line 2 "common/template.hpp"

#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")

#line 2 "common/alias.hpp"


// using namespace std::views;
// using namespace boost::multiprecision;

// --- 型エイリアス ---
using ull = unsigned long long;
template <typename T> using vec = vector<T>;
template <typename T> using vvec = vector<vector<T>>;
template <typename T> using p_queue = priority_queue<T>;
template <typename T> using rp_queue = priority_queue<T, vec<T>, greater<T>>;

// --- 黒魔術 ---
#define int ll

// --- 制御マクロ ---
#define rep(i, n) for (ll i = 0; i < n; ++i)
#define all(v) begin(v), end(v)
// #define BIT(n) (1LL << (n))
#define MAX(type) numeric_limits<type>::max()
#define MIN(type) numeric_limits<type>::min()
#define yes cout << "Yes" << endl
#define no cout << "No" << endl
#define pb push_back
#define mp make_pair
#define fir first
#define sec second

// --- 定数 ---
constexpr ll INF = 1LL << 60;

inline signed bit_width(ll x) { return bit_width((ull)x); }
inline ull bit_ceil(ll x) { return bit_ceil((ull)x); }
#line 2 "common/concepts.hpp"

#line 4 "common/concepts.hpp"

#line 2 "common/debug.hpp"

#line 4 "common/debug.hpp"

// --- デバッグ ---
#ifndef ONLINE_JUDGE
// #define printd(x) cerr << #x << ": " << x << endl;
const string _TERM_ESC = "\033";
const string _TERM_BOLD = _TERM_ESC + "[1m";
const string _TERM_DECO_RESET = _TERM_ESC + "[0m";
const string _TERM_FORE_RED = _TERM_ESC + "[31m";
const string _TERM_FORE_RESET = _TERM_ESC + "[39m";
const string _TERM_BACK_RED = _TERM_ESC + "[41m";
const string _TERM_BACK_RESET = _TERM_ESC + "[49m";

#define line_debug() cerr << "line: " << __LINE__ << endl;
#define coutd(x) cerr << "[debug] " << x;
#define printd(x)                                                              \
  cerr << _TERM_BOLD << _TERM_BACK_RED << "[debug] " << (#x) << " = " << (x)   \
       << _TERM_BACK_RESET << _TERM_DECO_RESET << endl;

#else

#define line_debug() ;
#define coutd(x) ;
#define printd(x) ;

#endif
#line 2 "common/int128_t.hpp"

#line 4 "common/int128_t.hpp"

using int128_t = __int128_t;
using uint128_t = __uint128_t;
using lll = int128_t;
using ulll = uint128_t;

// https://kenkoooo.hatenablog.com/entry/2016/11/30/163533

ostream &operator<<(ostream &dest, lll value) {
  ostream::sentry s(dest);
  if (s) {
    lll tmp = value < 0 ? -value : value;
    char buffer[128];
    char *d = end(buffer);
    do {
      --d;
      *d = "0123456789"[tmp % 10];
      tmp /= 10;
    } while (tmp != 0);
    if (value < 0) {
      --d;
      *d = '-';
    }
    int len = end(buffer) - d;
    if (dest.rdbuf()->sputn(d, len) != len) {
      dest.setstate(ios_base::badbit);
    }
  }
  return dest;
}

lll string_to_lll(string &s) {
  lll ret = 0;
  for (int i = 0; i < s.length(); i++)
    if ('0' <= s[i] && s[i] <= '9')
      ret = 10 * ret + s[i] - '0';
  return ret;
}

istream &operator>>(istream &src, lll &value) {
  string s;
  src >> s;
  value = string_to_lll(s);
  return src;
}
#line 2 "common/print.hpp"

#line 4 "common/print.hpp"

// ---------------
// ----- TOC -----
template <typename T1, typename T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &p);
template <typename T1, typename T2>
istream &operator>>(istream &is, pair<T1, T2> &p);
template <typename T> ostream &operator<<(ostream &os, const vector<T> &v);
template <typename T>
ostream &operator<<(ostream &os, const vector<vector<T>> &v);
template <typename T>
ostream &operator<<(ostream &os, const vector<vector<vector<T>>> &v);
template <typename T> istream &operator>>(istream &is, vector<T> &v);
template <typename T, typename S>
ostream &operator<<(ostream &os, const map<T, S> &mp);
template <typename T> ostream &operator<<(ostream &os, const set<T> &st);
template <typename T> ostream &operator<<(ostream &os, const multiset<T> &st);
template <typename T> ostream &operator<<(ostream &os, queue<T> q);
template <typename T> ostream &operator<<(ostream &os, deque<T> q);
template <typename T> ostream &operator<<(ostream &os, stack<T> st);
template <class T, class Container, class Compare>
ostream &operator<<(ostream &os, priority_queue<T, Container, Compare> pq);
// --- END TOC ---
// ---------------

template <typename T1, typename T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &p) {
  os << "(" << p.first << "," << p.second << ")";
  return os;
}

template <typename T1, typename T2>
istream &operator>>(istream &is, pair<T1, T2> &p) {
  is >> p.first >> p.second;
  return is;
}

template <typename T> ostream &operator<<(ostream &os, const vector<T> &v) {
  os << "[";
  for (int i = 0; i < (int)v.size(); i++) {
    os << v[i] << (i + 1 != (int)v.size() ? ", " : "]");
  }
  return os;
}

template <typename T>
ostream &operator<<(ostream &os, const vector<vector<T>> &v) {
  for (int i = 0; i < (int)v.size(); i++) {
    os << v[i] << endl;
  }
  return os;
}

template <typename T>
ostream &operator<<(ostream &os, const vector<vector<vector<T>>> &v) {
  for (int i = 0; i < (int)v.size(); i++) {
    os << "i = " << i << endl;
    os << v[i];
  }
  return os;
}

template <typename T> istream &operator>>(istream &is, vector<T> &v) {
  for (T &in : v)
    is >> in;
  return is;
}

template <typename T, typename S>
ostream &operator<<(ostream &os, const map<T, S> &mp) {
  for (auto &[key, val] : mp) {
    os << key << ":" << val << " ";
  }
  return os;
}

template <typename T> ostream &operator<<(ostream &os, const set<T> &st) {
  os << "{";
  auto itr = st.begin();
  for (int i = 0; i < (int)st.size(); i++) {
    os << *itr << (i + 1 != (int)st.size() ? ", " : "}");
    itr++;
  }
  return os;
}

template <typename T> ostream &operator<<(ostream &os, const multiset<T> &st) {
  auto itr = st.begin();
  for (int i = 0; i < (int)st.size(); i++) {
    os << *itr << (i + 1 != (int)st.size() ? " " : "");
    itr++;
  }
  return os;
}

template <typename T> ostream &operator<<(ostream &os, queue<T> q) {
  while (q.size()) {
    os << q.front() << " ";
    q.pop();
  }
  return os;
}

template <typename T> ostream &operator<<(ostream &os, deque<T> q) {
  while (q.size()) {
    os << q.front() << " ";
    q.pop_front();
  }
  return os;
}

template <typename T> ostream &operator<<(ostream &os, stack<T> st) {
  while (st.size()) {
    os << st.top() << " ";
    st.pop();
  }
  return os;
}

template <class T, class Container, class Compare>
ostream &operator<<(ostream &os, priority_queue<T, Container, Compare> pq) {
  while (pq.size()) {
    os << pq.top() << " ";
    pq.pop();
  }
  return os;
}
#line 2 "common/util.hpp"

#line 5 "common/util.hpp"

// --- Utils ---

// 二分探索
template <typename T>
inline T bin_search(T ok, T ng, const function<bool(T)> is_ok) {
  assert(is_ok(ok) && !is_ok(ng));
  assert(ok < ng);
  while (abs(ok - ng) > 1) {
    T mid = (ok + ng) / 2;
    if (is_ok(mid))
      ok = mid;
    else
      ng = mid;
  }
  return ok;
}

// 順列全探索
inline void rep_perm(int n, function<void(vec<int> &)> f) {
  vec<int> v(n);
  iota(v.begin(), v.end(), 0);
  do {
    f(v);
  } while (next_permutation(v.begin(), v.end()));
}

inline void rep_bit(int n, function<void(int)> f) { rep(i, 1LL << n) f(i); }

// 配列 to string
template <typename T> inline string join(const vec<T> &v, string sep = " ") {
  string res = "";
  rep(i, v.size()) res += to_string(v[i]) + (i == v.size() - 1 ? "" : sep);
  return res;
}
template <typename T>
inline void join_out(ostream &os, const vec<T> &v, string sep = " ",
                     string end = "\n") {
  int n = v.size();
  rep(i, n) os << v[i] << (i == n - 1 ? end : sep);
}

template <typename T>
inline void transform(vec<T> &src, function<void(T &)> f) {
  for (auto &val : src)
    f(val);
}

// ベース指定ceil
inline ll ceil(ll x, ll base) { return (x + base - 1) / base * base; }
// ベース指定floor
inline ll floor(ll x, ll base) { return x / base * base; }

// 合計値を求める
// ll sum(const vec<ll> &v) { return accumulate(all(v), 0LL); }

// 可変引数min
template <class... T> auto min(T... a) {
  return min(initializer_list<common_type_t<T...>>{a...});
}

// 可変引数max
template <class... T> auto max(T... a) {
  return max(initializer_list<common_type_t<T...>>{a...});
}

template <class T> bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T> bool chmin(T &a, const T &b) {
  if (b < a) {
    a = b;
    return 1;
  }
  return 0;
}

// 3項間不等式
// 広義単調増加
inline bool is_increasing(int x, int y, int z) { return x <= y && y <= z; }

// 半開区間[x, z)にyが含まれるか?
inline bool is_contained(int x, int y, int z) { return x <= y && y < z; }

// 頂点(x, y)が範囲に含まれるか
inline bool is_contained(int H, int W, int x, int y) {
  return is_contained(0, x, H) && is_contained(0, y, W);
}

// rootに対し、aとbが同じ側にあるか (=は含まない)
inline bool is_same_side(int root, int a, int b) {
  return (root < a) == (root < b);
}

// vector継承にする?
template <typename T> struct vec_accumulate : public vec<T> {
  explicit vec_accumulate(vec<T> &v) : vec<T>(v.size()) {
    assert(v.size() > 0);
    this->at(0) = v[0];
    for (int i = 1; i < v.size(); ++i)
      this->at(i) = this->at(i - 1) + v[i];
  }

  T operator[](int i) {
    assert(is_contained(-1, i, this->size()));
    if (i == -1)
      return T();
    return this->at(i);
  }
};

// vector func
template <typename T> inline void unique_erase(vec<T> &v) {
  sort(all(v));
  v.erase(unique(all(v)), v.end());
}

void io_setup() {
  cin.tie(nullptr);
  ios::sync_with_stdio(false);
  cout << std::fixed << std::setprecision(15);
}
#line 12 "common/template.hpp"

#line 2 "math/pow.hpp"

#line 5 "math/pow.hpp"

// 繰り返し2乗法

constexpr ll powm(ll a, ll n, const ll mod) {
  lll ans = 1;
  while (n > 0) {
    if (n & 1)
      ans = ans * a % mod;
    a = ((lll)a) * a % mod;
    n >>= 1;
  }
  return ans;
}
#line 2 "datastructure/monoid/monofunc.hpp"

#line 2 "datastructure/monoid/monoid.hpp"

#line 4 "datastructure/monoid/monoid.hpp"

/*
template <class M>
concept MonoidConcept = requires(M &x, M::T a, M::T b) {
  typename M::T;
  { M::e() } -> std::same_as<typename M::T>;
  { M::op(a, b) } -> std::same_as<typename M::T>;
};
*/

template <class Type> class Monoid {
public:
  Monoid() = default;
  using T = Type;
  virtual T e() const = 0;
  virtual T op(T a, T b) const = 0;
};


template <class Type, class Mono> class Monofunc {
public:
  Monofunc() = default;
  using T = Type;
  using M = Mono;
  using MT = typename M::T;
  virtual T id() const = 0;
  virtual MT apply(T a, MT b) const = 0;
  virtual T merge(T before, T after) const = 0;
};


// T : Nodeの型, F : 操作情報
template <class F> struct LazySegmentTree {
private:
  using M = typename F::M;
  using FT = typename F::T;
  using MT = typename M::T;
  // 単位元 デフォルトでは、min(a, e) = min(e, a) = a
  const MT e;
  const FT id;
  // Monoids
  const M _monoid;
  const F _monofunc;
  // 演算
  // const function<T(T, T)> op;
  // const function<T(F, T)> update;
  // const function<F(F, F)> merge;
  // 要素数
  int32_t _n;
  int32_t _height;
  // SefTreeのデータ
  vec<MT> _data;
  vec<FT> _lazy;

  // 自分の遅延を解消して子に伝搬する
  inline void eval(int32_t k) {
    if (_lazy[k] == id)
      return;
    _data[k] = _monofunc.apply(_lazy[k], _data[k]);
    if (k < _n) {
      _lazy[k << 1 | 0] = _monofunc.merge(_lazy[k << 1 | 0], _lazy[k]);
      _lazy[k << 1 | 1] = _monofunc.merge(_lazy[k << 1 | 1], _lazy[k]);
    }
    _lazy[k] = id;
  }

public:
  // n: 要素数, e: 単位元, id: 操作情報の単位元, op: 演算, update:
  // ノードの更新(fn,val->val), merge:
  // 操作aがすでに行われている状態に操作bを適用したときの操作
  // TODO: 2つの実装が別れているのをどうにかする
  explicit inline LazySegmentTree(const int32_t n)
      : _monoid(M()), _monofunc(F()), e(_monoid.e()), id(_monofunc.id()) {
    _n = 1;
    _height = 1;
    while (_n < n)
      _n <<= 1, _height++;
    _data = vec<MT>(_n << 1, e);
    _lazy = vec<FT>(_n << 1, id);
  }
  explicit inline LazySegmentTree(vec<MT> &data)
      : _monoid(M()), _monofunc(F()), e(_monoid.e()), id(_monofunc.id()) {
    _n = 1;
    _height = 1;
    while (_n < data.size())
      _n <<= 1, _height++;
    _data = vec<MT>(_n << 1, e);
    _lazy = vec<FT>(_n << 1, id);
    rep(i, data.size()) _data[i + _n] = data[i];
    for (int i = _n - 1; i > 0; --i)
      _data[i] = _monoid.op(_data[i << 1], _data[i << 1 | 1]);
  }
  /*
  inline LazySegmentTree(const T e, const F id,
                         const function<T(T, T)> op,
                         const function<T(F, T)> update,
                         const function<F(F, F)> merge,
                         vec<T> &v)
      : e(e), id(id), op(op), update(update), merge(merge) {
    _n = 1;
    _height = 1;
    while (_n < v.size())
      _n <<= 1, _height++;
    _data.resize(_n << 1, e);
    for(int i=0; i<v.size(); ++i) _data[i + _n] = v[i];
    _lazy = vec<F>(_n << 1, id);
  }
  */

  inline void set(int32_t l, int32_t r, FT f) {
    /*
    eval(k);
    if (l <= a && b <= r) { // 完全に内側
      _lazy[k] = merge(f, _lazy[k]);
      eval(k);
    } else if (a < r && l < b) { // 一部区間が被る
      _set(l, r, f, (k << 1) + 1, a, (a + b) >> 1);
      _set(l, r, f, (k << 1) + 2, (a + b) >> 1, b);
      _data[k] = op(_data[(k << 1) + 1], _data[(k << 1) + 2]);
    }
    */
    // a, bはseg-index [a,b]
    int32_t a = l + _n, b = r + _n - 1;

    // 上から下へとlazyを伝搬させる
    for (int32_t i = _height; 0 < i; --i)
      eval(a >> i), eval(b >> i);
    // bを [a, b]から[a, b)にする
    for (b++; a < b; a >>= 1, b >>= 1) {
      if (a & 1)
        _lazy[a] = _monofunc.merge(_lazy[a], f), eval(a), a++;
      if (b & 1)
        --b, _lazy[b] = _monofunc.merge(_lazy[b], f), eval(b);
    }
    // a, bをseg-index [a,b]に戻す
    a = l + _n, b = r + _n - 1;
    // a,bを親に移しつつ、aが実在頂点の間
    while ((a >>= 1), (b >>= 1), a) {
      if (_lazy[a] == id) {
        // _data[(a << 1) | 0] = update(_lazy[(a << 1) | 0], _data[(a << 1) |
        // 0]); _data[(a << 1) | 1] = update(_lazy[(a << 1) | 1], _data[(a << 1)
        // | 1]); _data[a] = op(_data[(a << 1) | 0], _data[(a << 1) | 1]);
        _data[a] = _monoid.op(
            _monofunc.apply(_lazy[(a << 1) | 0], _data[(a << 1) | 0]),
            _monofunc.apply(_lazy[(a << 1) | 1], _data[(a << 1) | 1]));
      }
      if (_lazy[b] == id) {
        // _data[(b << 1) | 0] = update(_lazy[(b << 1) | 0], _data[(b << 1) |
        // 0]); _data[(b << 1) | 1] = update(_lazy[(b << 1) | 1], _data[(b << 1)
        // | 1]); _data[b] = op(_data[(b << 1) | 0], _data[(b << 1) | 1]);
        _data[b] = _monoid.op(
            _monofunc.apply(_lazy[(b << 1) | 0], _data[(b << 1) | 0]),
            _monofunc.apply(_lazy[(b << 1) | 1], _data[(b << 1) | 1]));
      }
    }
  }

  // [l, r)の区間に対するクエリを処理する
  // kはSegTree上のindex
  inline MT query(int32_t l, int32_t r) {
    // ↓再帰
    /*
    eval(k);
    if (r <= a || b <= l)
      return e;
    if (l <= a && b <= r)
      return _data[k];
    T l_val = _query(l, r, (k << 1) + 1, a, (a + b) >> 1);
    T r_val = _query(l, r, (k << 1) + 2, (a + b) >> 1, b);
    return op(l_val, r_val);
    */

    // a, bはseg-index [a,b]
    int32_t a = l + _n, b = r + _n - 1;
    // 上から下へとlazyを伝搬させる
    for (int32_t i = _height; 0 <= i; --i)
      eval(a >> i), eval(b >> i);
    // line_debug();
    // printd(_data);
    // printd(_lazy);
    MT vl = e, vr = e;
    // bを [a, b]から[a, b)にする
    for (b++; a < b; a >>= 1, b >>= 1) {
      if (a & 1)
        vl = _monoid.op(vl, _monofunc.apply(_lazy[a], _data[a])), a++;
      if (b & 1)
        b--, vr = _monoid.op(_monofunc.apply(_lazy[b], _data[b]), vr);
    }
    return _monoid.op(vl, vr);
  }
  inline MT get(int32_t i) { return query(i, i + 1); }
};
/*
template <typename T, typename F> using LazySegtree = LazySegmentTree<T, F>;

template <typename T, typename F> inline LazySegtree<T, F> RMQLazySeg(int n) {
  return LazySegmentTree<T, F>(
      n, numeric_limits<T>::max(), 0, [](T a, T b) { return min(a, b); },
      [](F a, T b) { return b + a; }, [](F a, F b) { return b + a; });
}
*/


namespace Monofuncs {

template <class M>
class RangeSetMonofunc : public Monofunc<optional<typename M::T>, M> {
public:
  using T = optional<typename M::T>;
  using MT = typename M::T;
  // using T = optional<Type>;
  // using M = Monoids::SumMonoid<T>;
  T id() const override { return nullopt; }
  MT apply(T a, MT b) const override { return a ? a.value() : b; }
  T merge(T before, T after) const override { return after ? after : before; }
};
} // namespace Monofuncs

namespace Monoids {


template <class T = int> struct MinMonoid : public Monoid<T> {
  T e() const override { return numeric_limits<T>::max(); }
  T op(T a, T b) const override { return min(a, b); }
};


} // namespace Monoids

signed main() {
  int N, M, Q;
  cin >> N >> M >> Q;
  struct Elevator {
    int d, a, b;
    bool operator<(const Elevator &e) const { return d < e.d; }
    bool operator>(const Elevator &e) const { return d > e.d; }
  };
  priority_queue<Elevator, vec<Elevator>, greater<Elevator>> elevators;
  rep(i, M) {
    Elevator e;
    cin >> e.d >> e.a >> e.b;
    elevators.push(e);
  }
  struct Query {
    int index;
    int e, s, t;
    bool operator<(const Query &q) const { return e < q.e; }
    bool operator>(const Query &q) const { return e > q.e; }
  };
  priority_queue<Query, vec<Query>, greater<Query>> queries;
  rep(i, Q) {
    Query q;
    cin >> q.e >> q.s >> q.t;
    q.index = i;
    queries.push(q);
  }

  LazySegmentTree<Monofuncs::RangeSetMonofunc<Monoids::MinMonoid<int>>> seg(N);
  seg.set(0, N, 0);

  vec<int> ans(Q, -1);

  while(!elevators.empty() || !queries.empty()) {
    if(!elevators.empty()) {
      auto e = elevators.top();
      elevators.pop();
      int date = e.d;
      while(!queries.empty() && queries.top().e <= date) {
        auto q = queries.top();
        queries.pop();
        if(q.t <= q.s) {
          ans[q.index] = 1;
          continue;
        } else {
          int res = seg.query(q.s, q.t);
          ans[q.index] = res;
        }
      }
      seg.set(e.a, e.b, 1);
      /*
      rep(i, N) {
        printd(i);
        printd(seg.get(i));
      }
      */
    } else {
      while(!queries.empty()) {
        auto q = queries.top();
        queries.pop();
        if(q.t <= q.s) {
          ans[q.index] = 1;
          continue;
        } else {
          int res = seg.query(q.s, q.t);
          ans[q.index] = res;
        }
      }
    }
  }
  rep(i, Q) {
    assert(ans[i] == 1 || ans[i] == 0);
    if(ans[i]) yes;
    else no;
  }
}
accuracy: 1
time_ms: 240
memory_kb: 16328
final_rank: 16

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll = long long;
#define all(a) (a).begin(), a.end()
#define rep(i,n) for(ll i = 0; i < n; i++)

struct UnionFind {
    vector<int> data;
    vector<int> mx;

    UnionFind() = default;

    explicit UnionFind(size_t sz) : data(sz, -1), mx(sz) {
        rep(i,sz) mx[i] = i;
    }

    bool unite(int x, int y) {
        x = find(x);
        y = find(y);
        if(x == y) return false;
        if(data[x] > data[y]) swap(x, y);
        mx[x] = max(mx[x], mx[y]);
        data[x] += data[y];
        data[y] = x;
        return true;
    }

    int find(int x) { return data[x] < 0 ? x : data[x] = find(data[x]); }

    int size(int x) { return -data[x]; }

    bool same(int x, int y) { return find(x) == find(y); }

    int get(int x) { return mx[find(x)]; }
};

int main(){
    int n,m,q;
    cin >> n >> m >> q;

    vector<array<int, 4>> a(m + q, array<int, 4>());
    rep(i,m + q){
        cin >> a[i][0] >> a[i][2] >> a[i][3];
        if(i < m) a[i][1] = q;
        else a[i][1] = i - m;
    }

    sort(all(a));

    UnionFind uf(n + 1);
    vector<string> ans(q);

    rep(_i, m + q){
        auto [t, i, l, r] = a[_i];

        if(i == q){
            while(!uf.same(l, r)){
                if(uf.same(l, l+1)){
                    l = uf.get(l);
                }else{
                    uf.unite(l, l + 1);
                }
            }
        }
        else{
            ans[i] = (r <= l || uf.same(l, r)) ? "Yes" : "No";
        }
    }


    rep(i,q){
        cout << ans[i] << endl;
    }
}
accuracy: 1
time_ms: 180
memory_kb: 10108
final_rank: 10

code_snippet: #include <bits/stdc++.h>
#ifndef ATCODER_SEGTREE_HPP
#define ATCODER_SEGTREE_HPP 1

#include <algorithm>
#ifndef ATCODER_INTERNAL_BITOP_HPP
#define ATCODER_INTERNAL_BITOP_HPP 1

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

namespace internal {

// @param n `0 <= n`
// @return minimum non-negative `x` s.t. `n <= 2**x`
int ceil_pow2(int n) {
    int x = 0;
    while ((1U << x) < (unsigned int)(n)) x++;
    return x;
}

// @param n `1 <= n`
// @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0`
int bsf(unsigned int n) {
#ifdef _MSC_VER
    unsigned long index;
    _BitScanForward(&index, n);
    return index;
#else
    return __builtin_ctz(n);
#endif
}

}  // namespace internal

}  // namespace atcoder

#endif  // ATCODER_INTERNAL_BITOP_HPP

#include <cassert>
#include <vector>

namespace atcoder {

template <class S, S (*op)(S, S), S (*e)()> struct segtree {
  public:
    segtree() : segtree(0) {}
    segtree(int n) : segtree(std::vector<S>(n, e())) {}
    segtree(const std::vector<S>& v) : _n(int(v.size())) {
        log = internal::ceil_pow2(_n);
        size = 1 << log;
        d = std::vector<S>(2 * size, e());
        for (int i = 0; i < _n; i++) d[size + i] = v[i];
        for (int i = size - 1; i >= 1; i--) {
            update(i);
        }
    }

    void set(int p, S x) {
        assert(0 <= p && p < _n);
        p += size;
        d[p] = x;
        for (int i = 1; i <= log; i++) update(p >> i);
    }

    S get(int p) {
        assert(0 <= p && p < _n);
        return d[p + size];
    }

    S prod(int l, int r) {
        assert(0 <= l && l <= r && r <= _n);
        S sml = e(), smr = e();
        l += size;
        r += size;

        while (l < r) {
            if (l & 1) sml = op(sml, d[l++]);
            if (r & 1) smr = op(d[--r], smr);
            l >>= 1;
            r >>= 1;
        }
        return op(sml, smr);
    }

    S all_prod() { return d[1]; }

    template <bool (*f)(S)> int max_right(int l) {
        return max_right(l, [](S x) { return f(x); });
    }
    template <class F> int max_right(int l, F f) {
        assert(0 <= l && l <= _n);
        assert(f(e()));
        if (l == _n) return _n;
        l += size;
        S sm = e();
        do {
            while (l % 2 == 0) l >>= 1;
            if (!f(op(sm, d[l]))) {
                while (l < size) {
                    l = (2 * l);
                    if (f(op(sm, d[l]))) {
                        sm = op(sm, d[l]);
                        l++;
                    }
                }
                return l - size;
            }
            sm = op(sm, d[l]);
            l++;
        } while ((l & -l) != l);
        return _n;
    }

    template <bool (*f)(S)> int min_left(int r) {
        return min_left(r, [](S x) { return f(x); });
    }
    template <class F> int min_left(int r, F f) {
        assert(0 <= r && r <= _n);
        assert(f(e()));
        if (r == 0) return 0;
        r += size;
        S sm = e();
        do {
            r--;
            while (r > 1 && (r % 2)) r >>= 1;
            if (!f(op(d[r], sm))) {
                while (r < size) {
                    r = (2 * r + 1);
                    if (f(op(d[r], sm))) {
                        sm = op(d[r], sm);
                        r--;
                    }
                }
                return r + 1 - size;
            }
            sm = op(d[r], sm);
        } while ((r & -r) != r);
        return 0;
    }

  private:
    int _n, size, log;
    std::vector<S> d;

    void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }
};

}  // namespace atcoder

#endif  // ATCODER_SEGTREE_HPP

using namespace std;
using namespace atcoder;
using ll=long long;
using ld=long double;
using vll=vector<ll>;
using pll=pair<ll,ll>;
using mpll=map<ll,ll>;
using vvll=vector<vector<ll>>;
using vpll=vector<pair<ll,ll>>;
using vstr=vector<string>;
using Graph=vvll;
const ll INF=0x1fffffffffffffff;
const ll MOD=998244353;
const ll MODD=1000000007;
const ld PI=3.1415926535897932;
#define overload4(_1,_2,_3,_4,name,...) name
#define rep1(a) for(ll i=0;i<a;i++)
#define rep2(i,a) for(ll i=0;i<a;i++)
#define rep3(i,a,b) for(ll i=a;i<b;i++)
#define rep4(i,a,b,c) for(ll i=a;i<b;i+=c)
#define rep(...) overload4(__VA_ARGS__,rep4,rep3,rep2,rep1)(__VA_ARGS__)
#define rrep1(n) for(ll i=(n)-1;i>=0;i--)
#define rrep2(i,n) for(ll i=(n)-1;i>=0;i--)
#define rrep3(i,a,b) for(ll i=(b)-1;i>=(a);i--)
#define rrep4(i,a,b,c) for(ll i=a+(b-a-1)/c*c;i>=a;i-=c)
#define rrep(...) overload4(__VA_ARGS__,rrep4,rrep3,rrep2,rrep1)(__VA_ARGS__)
#define each(i,a) for(auto &i:a)
#define all(i) begin(i),end(i)
#define rall(i) rbegin(i),rend(i)
#define vec(type,name,...) vector<type>name(__VA_ARGS__)
#define vv(type,name,h,...) vector name(h,vector<type>(__VA_ARGS__))
template<class T>bool chmin(T&a,const T&b){if(a>b){a=b;return 1;}return 0;}
template<class T>bool chmax(T&a,const T&b){if(a<b){a=b;return 1;}return 0;}
template<class T>auto min(const T&a){return*min_element(all(a));}
template<class T>auto max(const T&a){return*max_element(all(a));}
template<class T>ll sum(const T&a){return accumulate(all(a),0LL);}
using ppll=pair<pll,pll>;

using S=ll;
S op(S a, S b){ return max(a,b); }
S e(){ return 0; }


int main(){
  ll n,m,q;
  cin>>n>>m>>q;
  vector<ppll> query(m+q);
  vstr ans(q);
  rep(m){
    ll d,a,b;
    cin>>d>>a>>b,a--,b--;
    query[i]={{d,INF},{a,b}};
  }
  rep(q){
    ll e,s,t;
    cin>>e>>s>>t,s--,t--;
    query[m+i]={{e,i},{s,t}};
  }
  sort(all(query));

  segtree<S,op,e> sg(n);
  rep(n)sg.set(i,i);
  rep(m+q){
    ll type=query[i].first.second;
    ll a=query[i].second.first,b=query[i].second.second;
    if(type==INF){
      ll val=sg.prod(0,b+1);
      sg.set(a,val);
    }
    else{
      ll val=sg.prod(0,a+1);
      ll na=a;
      while(val>na){
        na=val;
        val=sg.prod(0,na+1);
      }
      sg.set(a,val);
      if(val>=b)ans[type]="Yes";
      else ans[type]="No";
    }
  }
  rep(q)cout<<ans[i]<<endl;
  return 0;
}
accuracy: 1
time_ms: 200
memory_kb: 15360
final_rank: 15