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;
struct data {
  bitset<31> b;
};
struct data2 {
  int L, R, num;
};
data tree[600003];
data sagar[600003];
bitset<31> one(1);
bitset<31> zero(0);
data2 v[100004];
bool omg;
int our[100003];
void go(int node, int left, int right) {
  tree[left].b |= tree[node].b;
  tree[right].b |= tree[node].b;
}
void build(int node, int i, int j, int start, int finish, int val) {
  int left = node << 1;
  int right = left + 1;
  int mid = (i + j) >> 1;
  if (i > finish || j < start) return;
  if (i >= start && j <= finish) {
    tree[node].b |= (val);
    return;
  }
  build(left, i, mid, start, finish, val);
  build(right, mid + 1, j, start, finish, val);
}
void Rebuild(int node, int i, int j) {
  if (omg == true) return;
  int left = node << 1;
  int right = left + 1;
  int mid = (i + j) >> 1;
  if (i == j) {
    int messi = 0;
    for (int k = 0; k < 30; k++) {
      if (tree[node].b[k]) {
        messi += (1 << k);
        if (messi > 1073741823 || messi < 0) {
          messi = -1;
          omg = true;
          break;
        }
      }
    }
    our[i] = messi;
    sagar[node].b = tree[node].b;
    return;
  }
  go(node, left, right);
  Rebuild(left, i, mid);
  Rebuild(right, mid + 1, j);
  sagar[node].b = (sagar[left].b) & (sagar[right].b);
}
bitset<31> query(int node, int i, int j, int start, int finish) {
  if (i > finish || j < start) return one;
  if (i >= start && j <= finish) return sagar[node].b;
  int left = node << 1;
  int right = left + 1;
  int mid = (i + j) >> 1;
  return query(left, i, mid, start, finish) &
         (query(right, mid + 1, j, start, finish));
}
int main() {
  for (int i = 0; i < 31; i++) one[i] = true;
  int n, m, x, y, z;
  scanf("%d %d", &n, &m);
  for (int i = 1; i <= m; i++) {
    scanf("%d %d %d", &x, &y, &z);
    if (z != 0) build(1, 1, n, x, y, z);
    v[i - 1].L = x;
    v[i - 1].R = y, v[i - 1].num = z;
  }
  Rebuild(1, 1, n);
  if (omg) {
    printf("NO\n");
    return 0;
  }
  for (int i = 0; i < m; i++) {
    bitset<31> she;
    int L = v[i].L;
    int R = v[i].R;
    int num = v[i].num;
    she = query(1, 1, n, L, R);
    int barsa = 0;
    for (int k = 0; k < 30; k++) {
      if (she[k]) barsa += (1 << k);
      if (barsa > 1073741823 || barsa < 0) {
        barsa = -1;
        break;
      }
    }
    if (barsa != num) {
      printf("NO\n");
      return 0;
    }
  }
  printf("YES\n");
  for (int i = 1; i <= n; i++) printf("%d ", our[i]);
  return 0;
}
