// Original C++ solution (slower):
// 基本テンプレート

 

#include <iostream>

#include <iomanip>

#include <cstdio>

#include <string>

#include <cstring>

#include <deque>

#include <list>

#include <queue>

#include <stack>

#include <vector>

#include <utility>

#include <algorithm>

#include <map>

#include <set>

#include <complex>

#include <cmath>

#include <limits>

#include <cfloat>

#include <climits>

#include <ctime>

#include <cassert>

#include <numeric>

#include <fstream>

#include <functional>

using namespace std;

 

#define rep(i,a,n) for(int (i)=(a); (i)<(n); (i)++)

#define repq(i,a,n) for(int (i)=(a); (i)<=(n); (i)++)

#define repr(i,a,n) for(int (i)=(a); (i)>=(n); (i)--)

#define debug(...) fprintf(stderr, __VA_ARGS__)

#define int long long int

 

template<typename T> void chmax(T &a, T b) {a = max(a, b);}

template<typename T> void chmin(T &a, T b) {a = min(a, b);}

template<typename T> void chadd(T &a, T b) {a = a + b;}

 

typedef pair<int, int> pii;

typedef long long ll;

 

int dx[] = {0, 0, 1, -1};

int dy[] = {1, -1, 0, 0};

const ll INF = 1001001001001001LL;

const ll MOD = 1000000007LL;

 

struct Query {

    int day, lhs, rhs, mode, idx;

    bool operator<(const Query &q) const {

        if(day != q.day) return day < q.day;

        return mode < q.mode;

    }

};



// Abstract Segment Tree (抽象・汎化セグメント木)

// Verified: AOJ DSL_2_A: Range Minimum Query (int型のみ)



const int SIZE = 1 << 17; // 2^17 = 131072

template<typename T>

struct segtree {

    // ノード、単位元

    T node[2*SIZE], I;



    // オペレーション (update, query の 2 つが必要？)

    T (*upd_f)(T, T), (*qry_f)(T, T);



    // 演算子と単位元をセットし、全ての node を単位元で初期化

    segtree(T (*op1)(T, T), T (*op2)(T, T), T X) {

        upd_f = op1;

        qry_f = op2;

        I = X;

        fill(node, node+2*SIZE, I);

    }



    // 配列 vec の値で初期化

    void init(vector<T> vec) {

        int N = (int)vec.size();

        for(int i=0; i<N; i++) {

            node[SIZE-1+i] = vec[i];

        }

        for(int i=SIZE-2; i>=0; i--) {

            node[i] = qry_f(node[2*i+1], node[2*i+2]);

        }

    }



    // 場所 idx に値 val を反映 (upd_f を用いて update)

    void update(int idx, T val) {

        idx += SIZE - 1;

        node[idx] = upd_f(node[idx], val);

        while(idx > 0) {

            // 登るときは qry_f を使うことに注意！！！

            idx = (idx - 1) / 2;

            node[idx] = qry_f(node[2*idx+1], node[2*idx+2]);

        }

    }



    // 半開区間 [a, b) に対してクエリを投げる

    // (qry_f を用いて処理)

    T query(int a, int b, int l=0, int r=SIZE, int k=0) {

        if(b <= l || r <= a) return I;

        if(a <= l && r <= b) return node[k];

        int mid = (l + r) / 2;

        T vl = query(a, b, l, mid, 2*k+1);

        T vr = query(a, b, mid, r, 2*k+2);

        return qry_f(vl, vr);

    }

};



// [[つかいかた]]

// update 用と query 用の関数と単位元 (関数を噛ませても結果が変わらないもの) を用意して宣言する

// 下の例だと、update 用の関数が upd で、query 用の関数が fnd で、単位元が INT_MAX



int upd(int a, int b) {return max(a, b);}

int fnd(int a, int b) {return max(a, b);}

segtree<int> seg(upd, fnd, -1);



signed main() {

    int N, M, Q; cin >> N >> M >> Q;



    vector<Query> querys;

    // Query: 1 -> 判定クエリ、 2 -> 設置クエリ

    for(int i=0; i<M; i++) {

        int D, A, B; cin >> D >> A >> B;

        querys.push_back(Query{D, A, B, 2, -1});

    }



    for(int i=0; i<Q; i++) {

        int E, S, T; cin >> E >> S >> T;

        querys.push_back(Query{E, S, T, 1, i});

    }



    vector<string> ans(Q);

    sort(querys.begin(), querys.end());

    for(int i=0; i<M+Q; i++) {

        if(querys[i].mode == 1) {

            int val = seg.query(0, querys[i].lhs + 1);

            while(1) {

                int tmp = seg.query(0, val + 1);

                if(tmp <= val) break;

                val = tmp;

            }

            if(val >= querys[i].rhs || querys[i].lhs >= querys[i].rhs) {

                ans[ querys[i].idx ] = "Yes";

            }

            else {

                ans[ querys[i].idx ] = "No";

            }

            seg.update(querys[i].lhs, val);

        }

        else {

            int idx = querys[i].lhs, val = querys[i].rhs;

            seg.update(idx, val);

        }

    }



    for(int i=0; i<Q; i++) {

        cout << ans[i] << endl;

    }

    return 0;

}


// Optimized solution to the same problem (faster):
#include <bits/stdc++.h>



using namespace std;



#define int long long

#define all(v) (v).begin(), (v).end()

#define resz(v, ...) (v).clear(), (v).resize(__VA_ARGS__)

#define reps(i, m, n) for(int i = (int)(m); i < (int)(n); i++)

#define rep(i, n) reps(i, 0, n)



template<class T1, class T2> void chmin(T1 &a, T2 b){if(a>b)a=b;}

template<class T1, class T2> void chmax(T1 &a, T2 b){if(a<b)a=b;}



using Pi = pair<int, int>;

using Tapris = tuple<int, int, int, int, int>;

using vint = vector<int>;



const int inf = 1LL << 55;

const int mod = 1e9 + 7;



struct SegmentTree {

  vint data;

  vint lazy;

  int sz;

  SegmentTree(int n) {

    sz = 1; while(sz < n) sz *= 2;

    resz(data, 2*sz-1);

    rep(i, sz) data[i+sz-1] = i+1;

    for(int i = sz-2; i >= 0; --i) {

      data[i] = max(data[2*i+1], data[2*i+2]);

    }

    resz(lazy, 2*sz-1, -1);

  }

  void push(int k, int l, int r) {

    if(~lazy[k]) {

      chmax(data[k], lazy[k]);

      if(r-l > 1) {

	chmax(lazy[2*k+1], lazy[k]);

	chmax(lazy[2*k+2], lazy[k]);

      }

      lazy[k] = -1;

    }

  }

  void update(int a, int b, int x, int k, int l, int r) {

    push(k, l, r);

    if(r <= a || b <= l) return;

    if(a <= l && r <= b) {

      chmax(lazy[k], x);

      push(k, l, r);

      return;

    }

    update(a, b, x, 2*k+1, l, (l+r)/2);

    update(a, b, x, 2*k+2, (l+r)/2, r);

    data[k] = max(data[2*k+1], data[2*k+2]);

  }

  void update(int a, int b, int x) {

    update(a, b, x, 0, 0, sz);

  }

  int query(int a, int b, int k, int l, int r) {

    push(k, l, r);

    if(r <= a || b <= l) return -1;

    if(a <= l && r <= b) return data[k];

    int vl = query(a, b, 2*k+1, l, (l+r)/2);

    int vr = query(a, b, 2*k+2, (l+r)/2, r);

    return max(vl, vr);

  }

  int query(int a, int b) {

    return query(a, b, 0, 0, sz);

  }

};



signed main() {

  cin.tie(0);

  ios_base::sync_with_stdio(0);

  cout << fixed << setprecision(12);



  int n, m, q;

  cin >> n >> m >> q;

  vint d(m), a(m), b(m);

  rep(i, m) cin >> d[i] >> a[i] >> b[i], --a[i];

  vint e(q), s(q), t(q);

  rep(i, q) cin >> e[i] >> s[i] >> t[i], --s[i];

  vector<Tapris> vec;

  rep(i, m) vec.emplace_back(d[i], 1, a[i], b[i], i);

  rep(i, q) vec.emplace_back(e[i], 0, s[i], t[i], i);

  sort(all(vec));

  SegmentTree seg(n);

  vector<string> ans(q);

  rep(i, vec.size()) {

    int v, w, x, y, z;

    tie(v, w, x, y, z) = vec[i];

    if(w == 0) {

      if(x+1 >= y) {

	ans[z] = "Yes";

	continue;

      }

      int mr = seg.query(x, x+1);

      int tmp = seg.query(x, mr);

      while(mr != tmp) {

	mr = tmp;

	tmp = seg.query(x, mr);

      }

      ans[z] = (mr >= y ? "Yes" : "No");

      seg.update(x, mr, mr);

    } else {

      seg.update(x, y, y);

    }

  }

  rep(i, ans.size()) cout << ans[i] << endl;



  return 0;

}




// Fastest known solution for this problem: