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;
int n, m;
int l[100500];
int r[100500];
int val[100500];
int t[400500];
int t2[400500];
int mas[100500];
int INF = 0;
void build(int v, int tl, int tr) {
  if (tl == tr)
    t[v] = 0;
  else {
    int mid = (tl + tr) >> 1;
    build(v << 1, tl, mid);
    build((v << 1) + 1, mid + 1, tr);
    t[v] = 0;
  }
}
void update(int v, int tl, int tr, int ql, int qr, int nval) {
  if (ql > qr) return;
  if (tl == ql && tr == qr) {
    t[v] = t[v] | nval;
  } else {
    int mid = (tl + tr) >> 1;
    update(v << 1, tl, mid, ql, min(qr, mid), nval);
    update((v << 1) + 1, mid + 1, tr, max(ql, mid + 1), qr, nval);
  }
}
void dfs(int v, int tl, int tr, int curr) {
  if (tl == tr) {
    mas[tl] = curr | t[v];
  } else {
    int mid = (tl + tr) >> 1;
    dfs(v << 1, tl, mid, curr | t[v]);
    dfs((v << 1) + 1, mid + 1, tr, curr | t[v]);
  }
}
void build2(int v, int tl, int tr) {
  if (tl == tr) {
    t[v] = mas[tl];
  } else {
    int mid = (tl + tr) >> 1;
    build2(v << 1, tl, mid);
    build2((v << 1) + 1, mid + 1, tr);
    t[v] = t[v << 1] & t[(v << 1) + 1];
  }
}
int query(int v, int tl, int tr, int ql, int qr) {
  if (ql > qr) return INF;
  if (tl == ql && tr == qr) {
    return t[v];
  } else {
    int mid = (tl + tr) >> 1;
    return query(v << 1, tl, mid, ql, min(qr, mid)) &
           query((v << 1) + 1, mid + 1, tr, max(ql, mid + 1), qr);
  }
}
int main() {
  for (int i = 29; i >= 0; i--) {
    INF += (1 << i);
  }
  cin >> n >> m;
  build(1, 1, n);
  for (int i = 0; i < m; i++) {
    cin >> l[i] >> r[i] >> val[i];
    update(1, 1, n, l[i], r[i], val[i]);
  }
  dfs(1, 1, n, 0);
  build2(1, 1, n);
  for (int i = 0; i < m; i++) {
    if (query(1, 1, n, l[i], r[i]) != val[i]) {
      cout << "NO";
      return 0;
    }
  }
  cout << "YES\n";
  for (int i = 1; i <= n; i++) cout << mas[i] << " ";
  return 0;
}
