Description
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 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.
Sample Input
3 1 1 3 3
YES 3 3 3
3 2 1 3 3 1 3 2
NO
/**
题意:给n个数和m个操作,每个操作形如: l r x, 表示a[l] & a[l+1] & ... &a[r] = x;
问:是否存在这样一个序列满足所给操作?
有:输出YES,并输出这个序列。
没有:输出NO。
分析:考虑a[i],对于所有包含它的操作,如果取与操作后为x,
则x的二进制为1的位上,a[i]也为1。
其他位都为0肯定是满足的。
那么我们可以对所有x取或,得到的就是a[i]。
线段树区间操作就不多说了。
最后,检验序列是否符合要求。
*/
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<set>
using namespace std;
const int N = 100001;
int ans[N],mak[N<<2];
int ql[N],qr[N],qx[N];
void pushdown(int rt)
{
if(!mak[rt]) return ;
mak[rt<<1]|=mak[rt];
mak[rt<<1|1]|=mak[rt];
mak[rt] = 0;
}
void update(int L, int R, int x, int l, int r, int rt)
{
if(L<=l && R>=r)
{
mak[rt]|=x;
return;
}
int m = l+r>>1;
if(L<=m) update(L,R,x,l,m,rt<<1);
if(R>m) update(L,R,x,m+1,r,rt<<1|1);
}
void solve(int l, int r, int rt)
{
if(l==r)
{
ans[l] = mak[rt];
return ;
}
int m = l+r>>1;
pushdown(rt);
solve(l,m,rt<<1);
solve(m+1,r,rt<<1|1);
}
void build(int l, int r, int rt)
{
if(l==r)
{
mak[rt] = ans[l];
return ;
}
int m = l+r>>1;
build(l,m,rt<<1);
build(m+1,r,rt<<1|1);
mak[rt] = mak[rt<<1]&mak[rt<<1|1];
}
int query(int L, int R, int l, int r, int rt)
{
if(L<=l && R>=r) return mak[rt];
int m = l+r>>1;
int s = (1<<30)-1;
if(L<=m) s&=query(L,R,l,m,rt<<1);
if(R>m) s&=query(L,R,m+1,r,rt<<1|1);
return s;
}
int main()
{
int i,j,k,m,n;
while(scanf("%d %d",&n,&m)==2)
{
memset(mak,0,sizeof(mak));
for(i=1; i<=m; i++)
{
scanf("%d%d%d",ql+i,qr+i,qx+i);
update(ql[i],qr[i],qx[i],1,n,1);
}
solve(1,n,1);
build(1,n,1);
bool ok = true;
for(i=1; i<=m; i++)
{
int a = query(ql[i],qr[i],1,n,1);
if(a!=qx[i])
{
ok = false;
break;
}
}
if(!ok)
{
puts("NO");
continue;
};
puts("YES");
for(i=1; i<n; i++) printf("%d ",ans[i]);
printf("%d\n",ans[n]);
}
return 0;
}