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>
const long long INF = (1 << 30) - 1;
const int MAXN = 100001;
struct Node {
  int l, r;
  long long num;
  long long num2;
  long long delta;
};
int n, m;
long long t[MAXN];
int l[MAXN], r[MAXN];
long long q[MAXN];
Node tree[MAXN << 2];
void build(int cur, int l, int r) {
  tree[cur].l = l;
  tree[cur].r = r;
  tree[cur].delta = tree[cur].num = tree[cur].num2 = 0;
  if (l + 1 != r) {
    tree[cur].delta = 0;
    build((cur << 1) + 1, l, (l + r) >> 1);
    build((cur << 1) + 2, (l + r) >> 1, r);
  }
}
void update(int cur) {
  tree[(cur << 1) + 1].delta |= tree[cur].delta;
  tree[(cur << 1) + 2].delta |= tree[cur].delta;
  tree[(cur << 1) + 1].num |= tree[cur].delta;
  tree[(cur << 1) + 2].num |= tree[cur].delta;
  tree[(cur << 1) + 1].num2 |= tree[cur].delta;
  tree[(cur << 1) + 2].num2 |= tree[cur].delta;
  tree[cur].delta = 0;
}
void change(int cur, int l, int r, int delta) {
  if (l <= tree[cur].l && tree[cur].r <= r) {
    tree[cur].delta |= delta;
    tree[cur].num |= delta;
    tree[cur].num2 |= delta;
  } else {
    if (tree[cur].delta != 0) update(cur);
    int mid = (tree[cur].l + tree[cur].r) >> 1;
    if (l < mid) change((cur << 1) + 1, l, r, delta);
    if (r > mid) change((cur << 1) + 2, l, r, delta);
    tree[cur].num = tree[(cur << 1) + 1].num | tree[(cur << 1) + 2].num;
    tree[cur].num = tree[(cur << 1) + 1].num & tree[(cur << 1) + 2].num;
  }
}
long long query(int cur, int l, int r) {
  if (l <= tree[cur].l && tree[cur].r <= r) {
    return tree[cur].num2;
  } else {
    if (tree[cur].delta != 0) update(cur);
    int mid = (tree[cur].l + tree[cur].r) >> 1;
    long long ans = INF;
    if (l < mid) ans &= query((cur << 1) + 1, l, r);
    if (r > mid) ans &= query((cur << 1) + 2, l, r);
    return ans;
  }
}
int main() {
  scanf("%d%d", &n, &m);
  memset(t, 0LL, sizeof(t));
  build(0, 1, n + 1);
  for (int i = 1; i <= m; i++) {
    scanf("%d%d%I64d", &l[i], &r[i], &q[i]);
    change(0, l[i], r[i] + 1, q[i]);
  }
  bool ok = true;
  for (int i = 1; i <= m; i++) {
    long long te = query(0, l[i], r[i] + 1);
    if (te != q[i]) {
      ok = false;
      break;
    }
  }
  if (ok) {
    printf("YES\n");
    for (int i = 1; i <= n; i++) {
      printf("%I64d ", query(0, i, i + 1));
    }
    printf("\n");
  } else {
    printf("NO\n");
  }
  return 0;
}
