#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 3e5 + 5;
const int MAX_M = 3e5 + 5;
const int INF = 0x3f3f3f3f;
int N, M;
int T[MAX_M], L[MAX_M], R[MAX_M], X[MAX_M], K[MAX_M], D[MAX_M];
int max_num[MAX_N];
map<int, int> max_num_occur;
struct SegmentTree {
  int dat[MAX_N << 2];
  void build() { memset(dat, 0x3f, sizeof dat); }
  void update(int a, int b, int c, int l, int r, int k) {
    if (b <= l || r <= a) return;
    if (a <= l && r <= b) {
      dat[k] = min(dat[k], c);
      return;
    }
    if (dat[k] != INF) {
      dat[2 * k + 1] = min(dat[2 * k + 1], dat[k]);
      dat[2 * k + 2] = min(dat[2 * k + 2], dat[k]);
      dat[k] = INF;
    }
    update(a, b, c, l, (l + r) / 2, 2 * k + 1);
    update(a, b, c, (l + r) / 2, r, 2 * k + 2);
  }
  int query(int x, int l, int r, int k) {
    if (r - l == 1) return dat[k];
    if (dat[k] != INF) {
      dat[2 * k + 1] = min(dat[2 * k + 1], dat[k]);
      dat[2 * k + 2] = min(dat[2 * k + 2], dat[k]);
      dat[k] = INF;
    }
    int mid = (l + r) / 2;
    if (x < mid)
      return query(x, l, (l + r) / 2, 2 * k + 1);
    else
      return query(x, (l + r) / 2, r, 2 * k + 2);
  }
} st1;
struct SegmentTree2 {
  int dat[MAX_N << 2];
  int *src;
  void build(int l, int r, int k) {
    if (r - l == 1) {
      dat[k] = src[l];
      return;
    }
    build(l, (l + r) / 2, 2 * k + 1);
    build((l + r) / 2, r, 2 * k + 2);
    dat[k] = max(dat[2 * k + 1], dat[2 * k + 2]);
  }
  void update(int x, int v, int l, int r, int k) {
    if (r - l == 1) {
      dat[k] = v;
      return;
    }
    int mid = (l + r) / 2;
    if (x < mid)
      update(x, v, l, (l + r) / 2, 2 * k + 1);
    else
      update(x, v, (l + r) / 2, r, 2 * k + 2);
    dat[k] = max(dat[2 * k + 1], dat[2 * k + 2]);
  }
  int query(int a, int b, int l, int r, int k) {
    if (b <= l || r <= a) return INT_MIN;
    if (a <= l && r <= b) {
      return dat[k];
    }
    int vl = query(a, b, l, (l + r) / 2, 2 * k + 1);
    int vr = query(a, b, (l + r) / 2, r, 2 * k + 2);
    return max(vl, vr);
  }
} st2;
int main() {
  cin >> N >> M;
  memset(max_num, -1, sizeof max_num);
  st1.build();
  for (int i = 0; i < M; ++i) {
    scanf("%d", &T[i]);
    if (T[i] == 1) {
      scanf("%d%d%d", &L[i], &R[i], &X[i]);
      --L[i];
      st1.update(L[i], R[i], X[i], 0, N, 0);
    } else {
      scanf("%d%d", &K[i], &D[i]);
      --K[i];
      if (max_num[K[i]] == -1) {
        max_num[K[i]] = st1.query(K[i], 0, N, 0);
      }
    }
  }
  for (int i = 0; i < N; ++i) {
    if (max_num[i] == -1) {
      max_num[i] = st1.query(i, 0, N, 0);
    }
  }
  st2.src = max_num;
  st2.build(0, N, 0);
  bool exist_ans = true;
  for (int i = 0; i < M; ++i) {
    if (T[i] == 1) {
      if (st2.query(L[i], R[i], 0, N, 0) != X[i]) {
        exist_ans = 0;
        break;
      }
    } else {
      st2.update(K[i], D[i], 0, N, 0);
    }
  }
  if (!exist_ans) {
    printf("NO\n");
  } else {
    printf("YES\n");
    for (int i = 0; i < N; ++i) {
      max_num_occur[max_num[i]]++;
    }
    if (max_num_occur[INF] >= 2) {
      for (int i = 0; i < N; ++i) {
        if (max_num[i] == INF) {
          max_num[i] = (1 << 29);
          if (--max_num_occur[INF] == 0) {
            max_num[i] = (1 << 29) - 1;
          }
        }
      }
      for (int i = 0; i < N; ++i) {
        printf("%d ", max_num[i]);
      }
    } else {
      int res = 0;
      for (int i = 0; i < N; ++i) {
        if (max_num[i] == 0 || max_num[i] == INF) continue;
        if (--max_num_occur[max_num[i]] > 0) {
          int log2x = 31 - __builtin_clz(max_num[i]);
          max_num[i] = (1 << log2x) - 1;
        }
        res |= max_num[i];
      }
      int free_num = 0;
      for (int i = 29; i >= 0; --i) {
        if (res >> i & 1) continue;
        if (free_num + (1 << i) > (int)(1e9)) continue;
        free_num |= (1 << i);
      }
      for (int i = 0; i < N; ++i) {
        if (max_num[i] == INF) {
          printf("%d ", free_num);
        } else {
          printf("%d ", max_num[i]);
        }
      }
    }
  }
  return 0;
}
