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>
#pragma optimize("Ofast")
using namespace std;
int t, n, m, ql, qr;
struct node {
  int val, add;
} tree[400005];
void push_up(int pos) {
  tree[pos].val = tree[pos << 1].val & tree[pos << 1 | 1].val;
}
void push_down(int pos) {
  if (tree[pos].add) {
    tree[pos << 1].val |= tree[pos].add;
    tree[pos << 1].add |= tree[pos].add;
    tree[pos << 1 | 1].val |= tree[pos].add;
    tree[pos << 1 | 1].add |= tree[pos].add;
    tree[pos].add = 0;
  }
}
void UPD(int pos, int l, int r, int v) {
  if (l > qr || r < ql) return;
  if (tree[pos].val == r - l + 1) return;
  if (ql <= l && r <= qr) {
    tree[pos].val |= v;
    tree[pos].add |= v;
    return;
  }
  push_down(pos);
  int mid = (l + r) >> 1;
  if (ql <= mid) UPD(pos << 1, l, mid, v);
  if (mid < qr) UPD(pos << 1 | 1, mid + 1, r, v);
  push_up(pos);
  return;
}
int query(int pos, int l, int r) {
  if (ql <= l && r <= qr) {
    return tree[pos].val;
  }
  push_down(pos);
  int mid = (l + r) >> 1, res = (1 << 30) - 1;
  if (ql <= mid) res &= query(pos << 1, l, mid);
  if (mid < qr) res &= query(pos << 1 | 1, mid + 1, r);
  push_up(pos);
  return res;
}
map<pair<long long, long long>, int> mp;
int main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  ;
  cin >> n >> m;
  int a, b, c, ok = 1;
  while (m--) {
    cin >> a >> b >> c;
    if (mp.count({a, b})) {
      if (mp[{a, b}] != c) ok = 0;
    }
    mp[{a, b}] = c;
    if (!ok) continue;
    ql = a;
    qr = b;
    int now = query(1, 1, n);
    if ((c & now) == now)
      UPD(1, 1, n, c - now);
    else
      ok = 0;
  }
  if (!ok)
    cout << "NO\n";
  else {
    cout << "YES\n";
    for (int i = 1; i <= n; i++) {
      ql = qr = i;
      cout << query(1, 1, n) << ' ';
    }
  }
  return 0;
}
