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
import java.io.*;
import java.util.*;


public class Main 	{

    static PrintWriter out = new PrintWriter(new BufferedOutputStream(System.out));
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st = new StringTokenizer("");

    static String next() {
    	try	{
        while (!st.hasMoreTokens()) {
            String s = br.readLine();
            if (s == null) {
                return null;
            }
            st = new StringTokenizer(s);
        }
        return st.nextToken();
    	}	catch(Exception e)	{
    		return	null;
    	}
    }
    
    public static void main(String[] asda) throws Exception	{
    	
    	int N = Integer.parseInt( next() );
    	int M = Integer.parseInt( next() );
    	
    	int [][] v = new int [N + 2][31];
    	int [] a = new int [M];
    	int [] b = new int [M];
    	int [] c = new int [M];
    	for (int i = 0; i < M; i++)	{
    		a[i] = Integer.parseInt( next() );
    		b[i] = Integer.parseInt( next() );
    		c[i] = Integer.parseInt( next() );
    		
    		int x = c[i];
    		for (int k = 0; k < 31; k++)	if	( (x & (1 << k)) != 0 )	{
    			v[ a[i] ][k] += 1;
    			v[ b[i] + 1 ][k] += -1;
    		}
    	}
    	
    	// partial sums
    	int [] key = new int [N + 1];
    	for (int i = 1; i <= N; i++)	{
    		int x = 0;
    		for (int k = 0; k < 31; k++)	{
    			v[i][k] += v[i - 1][k];
    			if	( v[i][k] != 0 )
    				x |= 1 << k;
    		}
    		key[i] = x;
    	}
    	
    	//
    	BinarySegmentTree t = new BinarySegmentTree(N + 1);
    	for (int i = 1; i <= N; i++)
    		t.set(i, key[i]);
    	
    	
    	boolean ok = true;
    	for (int i = 0; i < M && ok; i++)	{
    		int L = a[i];
    		int R = b[i];
    		int ans = c[i];
    		int x = t.getCount(L, R);
    		
    //		out.println(x);
    		ok &= ans == x;
    	}
    	
    	out.println( ok ? "YES" : "NO" );
    	if	( ok )	{
    		out.print( key[1] );
    		for (int i = 2; i <= N; i++)
    			out.print(" " + key[i]);
    		out.println();
    	}
    	
    	out.flush();
    }
}



class BinarySegmentTree {
	
	int N;
	int [] tree;
	
	/**
	 * Crea un BinarySegmentTree para que soporte operaciones en el rango [0, size], inclusivo.
	 * @param size		La posicion maxima que manejara el arbol.
	 */
	public BinarySegmentTree(int size) {
		N = 1;
		while ( (N <<= 1) < size);
		tree = new int[N << 1];
	}

	/**
	 * Asigna el valor n en la posicion indicada
	 * Complejidad:		O(lg n)
	 * @param pos		Posicion del punto a agregar.
	 * @param n			Valor a asignar
	 */
	void set(int pos, int n) {
		pos += N;
		tree[pos] = n;
		pos >>= 1;
		while (pos > 0) {
			tree[pos] = tree[pos << 1] & tree[(pos << 1) + 1];
			pos >>= 1;
		}
   	}
	
	/**
	 * Cuenta el numero de puntos que estan dentro del rango [l, r], inclusivo.
	 * Complejidad:		O(lg l + lg r)
	 * @param l			Inicio del rango.
	 * @param r			Fin del rango.
	 * @return			Numero de puntos que contiene el rango especificado.
	 */
	int getCount(int l, int r) {
		l += N;
		r += N;
		int ans = (1 << 31) - 1;
		while (l <= r) {
			if (l == r)	return	ans & tree[l];
			if ((l & 1) == 1)	ans &= tree[l++];
			if ((r & 1) == 0)	ans &= tree[r--];
			l >>= 1;
			r >>= 1;
		}
		return ans;
	}
}

