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.
Examples
input
3 1
1 3 3
output
YES
3 3 3
input
3 2
1 3 3
1 3 2
output
NO
题意:
目的是构建一个序列a,满足m条限制.
限制形如<l,r,q>: a[l]&a[l+1]&...&a[r-1]&a[r]=q;(此处'&'为位运算的and操作).
题解:
首先考虑最暴力的情况
对于一个区间,区间与后得到ai,则ai的二进制表示下,如果第i位为一,那么这一个区间中所有数的第i位一定是一。
然后如果第i位为0,那么说明在区间中一定至少有一个数是零,可以查询区间中1的个数是不是等于区间长度,如果是的话就GG了,输出NO
上述的思路可以建30棵区间覆盖线段树,维护每一位。
然后你就光荣的TLE第九个点了,比较喜欢这种暴力思路的大佬可以考虑用差分或者树状数组去继续优化常数,应该是可以A的
像我这种蒟蒻就只能重构代码了。
其实可以压位
我们进行的区间覆盖,其实就是按位或运算,可以直接把三十颗线段树合到一棵,支持区间或修改,每次区间或上ai
但是之前判断是否GG的地方就要魔改了,不要慌,会改的更加简单,因为我们进行完所有的或操作之后,已经得到了那个我们需要的ans数组,只需要检查这个数组对于每个区间li-ri的区间与是否等于ai就可以了。
代码如下:
#include<ctime> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define lson root<<1 #define rson root<<1|1 using namespace std; struct oper { int l,r,a; } op[100010]; struct node { int l,r,lazy,sum; } tr[400010]; inline void push_up(int root) { tr[root].sum=tr[lson].sum&tr[rson].sum; } inline void push_down(int root) { tr[lson].sum|=tr[root].lazy; tr[lson].lazy|=tr[root].lazy; tr[rson].sum|=tr[root].lazy; tr[rson].lazy|=tr[root].lazy; tr[root].lazy=0; } inline void build(int root,int l,int r) { if(l==r) { tr[root].l=l; tr[root].r=r; return ; } tr[root].l=l; tr[root].r=r; register int mid=(l+r)>>1; build(lson,l,mid); build(rson,mid+1,r); } inline void update(int root,int l,int r,int val) { if(tr[root].l==l&&tr[root].r==r) { tr[root].sum|=val; tr[root].lazy|=val; return ; } if(tr[root].lazy) { push_down(root); } register int mid=(tr[root].l+tr[root].r)>>1; if(mid<l) { update(rson,l,r,val); } else { if(mid>=r) { update(lson,l,r,val); } else { update(lson,l,mid,val); update(rson,mid+1,r,val); } } push_up(root); } inline int query(int root,int l,int r) { if(tr[root].l==l&&tr[root].r==r) { return tr[root].sum; } if(tr[root].lazy) { push_down(root); } register int mid=(tr[root].l+tr[root].r)>>1; if(mid<l) { return query(rson,l,r); } else { if(mid>=r) { return query(lson,l,r); } else { return query(lson,l,mid)&query(rson,mid+1,r); } } } int main() { int n,m,flag=0; scanf("%d%d",&n,&m); build(1,1,n); for(int i=1; i<=m; i++) { scanf("%d%d%d",&op[i].l,&op[i].r,&op[i].a); update(1,op[i].l,op[i].r,op[i].a); } for(int i=1; i<=m; i++) { if(query(1,op[i].l,op[i].r)!=op[i].a) { flag=1; } } if(flag) { puts("NO"); } else { puts("YES"); for(int i=1; i<=n; i++) { printf("%d ",query(1,i,i)); } } }