#include <bits/stdc++.h>
using namespace std;
template <typename T, typename F>
struct SEGMENT_TREE {
  long long Li, Ri;
  long long pt = 0;
  vector<T> ST;
  vector<long long> L;
  vector<long long> R;
  vector<bool> lazy;
  void new_node() {
    ST.push_back(T{});
    L.push_back(0);
    R.push_back(0);
    lazy.push_back(false);
  }
  SEGMENT_TREE(long long a, long long b) {
    assert(a <= b);
    Li = a, Ri = b;
    new_node();
  }
  void build(vector<T> &vect) {
    assert(Ri - Li + 1 == (long long)vect.size());
    ST_build(0, Li, Ri, vect);
  }
  void insert(long long x, T nod) { ST_insert(0, Li, Ri, x, nod); }
  void update(long long x, F &up) { ST_update(0, Li, Ri, x, x, up); }
  void update(long long a, long long b, F &up) {
    ST_update(0, Li, Ri, a, b, up);
  }
  T query(long long x) { return ST_query(0, Li, Ri, x, x); }
  T query(long long a, long long b) { return ST_query(0, Li, Ri, a, b); }
  void ST_build(long long node, long long l, long long r, vector<T> &vect) {
    if (l == r) {
      ST[node] = vect[l - Li];
      return;
    } else {
      L[node] = ++pt;
      new_node();
      R[node] = ++pt;
      new_node();
    }
    long long mid = (l + r) / 2;
    ST_build(L[node], l, mid, vect);
    ST_build(R[node], mid + 1, r, vect);
    ST[node].merge(ST[L[node]], ST[R[node]]);
  }
  void ST_insert(long long node, long long l, long long r, long long x,
                 T &nod) {
    if (l != r) {
      if (L[node] == 0) {
        L[node] = ++pt;
        new_node();
      }
      if (R[node] == 0) {
        R[node] = ++pt;
        new_node();
      }
    }
    if (lazy[node]) {
      if (l != r) {
        ST[node].propagation(ST[L[node]], ST[R[node]]);
        lazy[L[node]] = true;
        lazy[R[node]] = true;
      }
      ST[node].update(l, r);
      lazy[node] = false;
    }
    if (l == r) {
      ST[node] = nod;
      return;
    }
    long long mid = (l + r) / 2;
    if (x <= mid)
      ST_insert(L[node], l, mid, x, nod);
    else
      ST_insert(R[node], mid + 1, r, x, nod);
    ST[node].merge(ST[L[node]], ST[R[node]]);
  }
  void ST_update(long long node, long long l, long long r, long long a,
                 long long b, F &up) {
    if (l != r) {
      if (L[node] == 0) {
        L[node] = ++pt;
        new_node();
      }
      if (R[node] == 0) {
        R[node] = ++pt;
        new_node();
      }
    }
    if (lazy[node]) {
      if (l != r) {
        ST[node].propagation(ST[L[node]], ST[R[node]]);
        lazy[L[node]] = true;
        lazy[R[node]] = true;
      }
      ST[node].update(l, r);
      lazy[node] = false;
    }
    if (r < a || l > b) return;
    if (a <= l && r <= b) {
      ST[node].push(up);
      if (l != r) {
        ST[node].propagation(ST[L[node]], ST[R[node]]);
        lazy[L[node]] = true;
        lazy[R[node]] = true;
      }
      ST[node].update(l, r);
      return;
    }
    long long mid = (l + r) / 2;
    ST_update(L[node], l, mid, a, b, up);
    ST_update(R[node], mid + 1, r, a, b, up);
    ST[node].merge(ST[L[node]], ST[R[node]]);
  }
  T ST_query(long long node, long long l, long long r, long long a,
             long long b) {
    if (l != r) {
      if (L[node] == 0) {
        L[node] = ++pt;
        new_node();
      }
      if (R[node] == 0) {
        R[node] = ++pt;
        new_node();
      }
    }
    if (lazy[node]) {
      if (l != r) {
        ST[node].propagation(ST[L[node]], ST[R[node]]);
        lazy[L[node]] = true;
        lazy[R[node]] = true;
      }
      ST[node].update(l, r);
      lazy[node] = false;
    }
    if (a <= l && r <= b) {
      return ST[node];
    }
    long long mid = (l + r) / 2;
    T qu;
    bool flag = false;
    if (a <= mid) {
      qu = ST_query(L[node], l, mid, a, b);
      flag = true;
    }
    if (b > mid) {
      T temp = ST_query(R[node], mid + 1, r, a, b);
      if (flag)
        qu.merge(qu, temp);
      else
        swap(qu, temp);
    }
    return qu;
  }
};
struct QUERY {
  long long may = 1e10;
};
struct NODE {
  long long may = 1e10;
  long long lazymay = 1e18;
  void merge(NODE &H1, NODE &H2) { may = max(H1.may, H2.may); }
  void push(QUERY &Q) { lazymay = Q.may; }
  void update(long long l, long long r) {
    may = min(may, lazymay);
    lazymay = 1e18;
  }
  void propagation(NODE &H1, NODE &H2) {
    H1.lazymay = min(H1.lazymay, lazymay);
    H2.lazymay = min(H2.lazymay, lazymay);
  }
};
const long long MAXN = 3e5 + 100;
long long arr[MAXN];
long long res[MAXN];
struct query {
  long long tp, a, b, c;
};
int32_t main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  for (long long i = 0; i < MAXN; i++) {
    arr[i] = -1;
  }
  long long N, M;
  cin >> N >> M;
  SEGMENT_TREE<NODE, QUERY> ST(1, N);
  vector<query> Q;
  for (long long i = 0; i < M; i++) {
    long long qu;
    cin >> qu;
    if (qu == 1) {
      long long a, b, x;
      cin >> a >> b >> x;
      Q.push_back({1, a, b, x});
      QUERY tp;
      tp.may = x;
      ST.update(a, b, tp);
    } else {
      long long pos, x;
      cin >> pos >> x;
      Q.push_back({2, pos, x});
      if (arr[pos] == -1) {
        arr[pos] = ST.query(pos).may;
      }
      NODE tp;
      tp.may = x;
      ST.insert(pos, tp);
    }
  }
  for (long long i = 1; i <= N; i++) {
    if (arr[i] == -1) {
      arr[i] = ST.query(i).may;
    }
  }
  map<long long, bool> mp;
  for (long long i = 1; i <= N; i++) {
    if (arr[i] == 1e10) {
      arr[i] = 1e9;
      continue;
    }
    if (!mp[arr[i]]) {
      mp[arr[i]] = true;
      res[i] = arr[i];
    }
  }
  for (long long x = 29; x >= 0; x--) {
    bool flag = false;
    for (long long i = 1; i <= N; i++) {
      if (res[i] & (1 << x)) flag = true;
    }
    if (flag) continue;
    for (long long i = 1; i <= N; i++) {
      if ((res[i] | (1 << x)) <= arr[i]) {
        res[i] = res[i] | (1 << x);
        break;
      }
    }
  }
  SEGMENT_TREE<NODE, QUERY> ST2(1, N);
  for (long long i = 1; i <= N; i++) {
    NODE tp;
    tp.may = res[i];
    ST2.insert(i, tp);
  }
  for (auto x : Q) {
    if (x.tp == 1) {
      if (ST2.query(x.a, x.b).may != x.c) {
        cout << "NO" << '\n';
        return 0;
      }
    } else {
      NODE tp;
      tp.may = x.b;
      ST2.insert(x.a, tp);
    }
  }
  cout << "YES" << '\n';
  for (long long i = 1; i <= N; i++) {
    cout << res[i] << " ";
  }
  cout << '\n';
  return 0;
}
