We'll call an array of n non-negative integers a[1], a[2], ..., a[n] interesting, if it meets m constraints. The i-th of the m constraints consists of three integers li, ri, qi (1 ≤ li ≤ ri ≤ n) meaning that value <image> should be equal to qi. 

Your task is to find any interesting array of n elements or state that such array doesn't exist.

Expression x&y means the bitwise AND of numbers x and y. In programming languages C++, Java and Python this operation is represented as "&", in Pascal — as "and".

Input

The first line contains two integers n, m (1 ≤ n ≤ 105, 1 ≤ m ≤ 105) — the number of elements in the array and the number of limits.

Each of the next m lines contains three integers li, ri, qi (1 ≤ li ≤ ri ≤ n, 0 ≤ qi < 230) describing the i-th limit.

Output

If the interesting array exists, in the first line print "YES" (without the quotes) and in the second line print n integers a[1], a[2], ..., a[n] (0 ≤ a[i] < 230) decribing the interesting array. If there are multiple answers, print any of them.

If the interesting array doesn't exist, print "NO" (without the quotes) in the single line.

Examples

Input

3 1
1 3 3


Output

YES
3 3 3


Input

3 2
1 3 3
1 3 2


Output

NO
#include <bits/stdc++.h>
using namespace std;
long long t[400010], nt[400010], color[400010];
int N, M;
struct q {
  long long l, r, d;
  q() {}
  q(long long l, long long r, long long d) : l(l), r(r), d(d) {}
} qq[100010];
void push(int v) {
  if (color[v]) {
    color[v * 2] |= color[v];
    color[v * 2 + 1] |= color[v];
    t[v * 2] |= color[v];
    t[v * 2 + 1] |= color[v];
  }
  color[v] = 0;
}
void upd(int l, int r, long long delta, int v = 1, int tl = 1, int tr = N) {
  if (l > r)
    return;
  else if (l == tl && r == tr) {
    color[v] |= delta;
    t[v] |= delta;
  } else {
    push(v);
    int tm = (tl + tr) / 2;
    upd(l, min(r, tm), delta, v * 2, tl, tm);
    upd(max(tm + 1, l), r, delta, v * 2 + 1, tm + 1, tr);
    t[v] = (t[v * 2] | t[v * 2 + 1]);
  }
}
long long get(int pos, int v = 1, int l = 1, int r = N) {
  if (l == r)
    return t[v];
  else {
    push(v);
    int m = (l + r) / 2;
    if (pos <= m)
      return get(pos, v * 2, l, m);
    else
      return get(pos, v * 2 + 1, m + 1, r);
  }
}
long long x(int l, int r, int v = 1, int tl = 1, int tr = N) {
  if (l > r)
    return -1;
  else if (l == tl && r == tr)
    return nt[v];
  else {
    int tm = (tl + tr) / 2;
    return x(l, min(r, tm), v * 2, tl, tm) &
           x(max(tm + 1, l), r, v * 2 + 1, tm + 1, tr);
  }
}
void build(int v = 1, int tl = 1, int tr = N) {
  if (tl == tr) {
    nt[v] = get(tl);
    if (nt[v] > (1 << 30)) {
      cout << "NO" << endl;
      exit(0);
    }
  } else {
    int tm = (tl + tr) / 2;
    build(v * 2, tl, tm);
    build(v * 2 + 1, tm + 1, tr);
    nt[v] = nt[v * 2] & nt[v * 2 + 1];
  }
}
int main() {
  cin >> N >> M;
  for (int i = 0; i < M; i++) {
    long long l, r, x;
    cin >> l >> r >> x;
    upd(l, r, x);
    qq[i] = {l, r, x};
  }
  build();
  for (int i = 0; i < M; i++) {
    if (x(qq[i].l, qq[i].r) != qq[i].d) {
      cout << "NO" << endl;
      return 0;
    }
  }
  cout << "YES" << endl;
  for (int i = 1; i <= N; i++) {
    cout << get(i) << " ";
  }
  cout << endl;
  return 0;
}
