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 integersa[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个位置1-n,再给m个区间,要m个区间的位置&后都符合q的值,不符合就NO,否者YES而且要输出所有位置的值。
思路:
这题想了一会感觉像线段树,结果敲完后总是WA3,最后发现了在查询的时候两个区间回溯的时候应该要&才能是正确的答案。
AC代码:
#include<iostream> #include<algorithm> #include<cstdio> using namespace std; const int T = 100000+50; #define lson (rt<<1) #define rson (rt<<1|1) struct node { int L,R,mid,v,ans; }tree[T<<2]; struct Line { int L,R,v; }li[T]; void Push_Down(int rt)//将数值向下传递 { if(tree[rt].v){ tree[lson].v |= tree[rt].v;//懒惰性标记 tree[rson].v |= tree[rt].v; tree[lson].ans |= tree[rt].ans;//区间值,一开始没将区间值也向下压了 tree[rson].ans |= tree[rt].ans; tree[rt].v = 0; } } void Push_Up(int rt)//向上找出最终区间的值 { tree[rt].ans = tree[lson].ans&tree[rson].ans; } void Build(int rt,int L,int R)//建立二叉树 { tree[rt].L = L,tree[rt].R = R; tree[rt].mid = (L+R)>>1; tree[rt].v = tree[rt].ans = 0; if(L==R)return; Build(lson,L,tree[rt].mid); Build(rson,tree[rt].mid+1,R); } void Insert(int rt,int L,int R,int v)//插入一段区间值 { if(L<=tree[rt].L&&R>=tree[rt].R){//符合即添加值 tree[rt].ans |= v; tree[rt].v |= v; return; } Push_Down(rt);//向下更新 if(R<=tree[rt].mid){ Insert(lson,L,R,v); } else if(L>tree[rt].mid){ Insert(rson,L,R,v); } else { Insert(lson,L,tree[rt].mid,v); Insert(rson,tree[rt].mid+1,R,v); } Push_Up(rt);//向上更新 } int query(int rt,int L,int R)//查询区间段 { if(L<=tree[rt].L&&R>=tree[rt].R){ return tree[rt].ans; } Push_Down(rt); int ans = 0; if(R<=tree[rt].mid){ ans += query(lson,L,R); } else if(L>tree[rt].mid){ ans += query(rson,L,R); } else { //这里需要注意一下,因为有可能左右两边是不同的值,之前一直是相加 //所以Wa了许多次 ans += query(lson,L,tree[rt].mid)&query(rson,tree[rt].mid+1,R); } Push_Up(rt); return ans; } void Task(int rt,int L,int R)//返回叶子节点的值 { if(L==R){ printf("%d ",tree[rt].v); return; } Push_Down(rt); Task(lson,L,tree[rt].mid); Task(rson,tree[rt].mid+1,R); } int main() { #ifdef zsc freopen("input.txt","r",stdin); #endif int n,m,i,j,k; while(~scanf("%d%d",&n,&m)) { Build(1,1,n); for(i=0;i<m;++i){ scanf("%d%d%d",&li[i].L,&li[i].R,&li[i].v); Insert(1,li[i].L,li[i].R,li[i].v); } bool flag = false; for(i=0;i<m&&!flag;++i){ if(query(1,li[i].L,li[i].R)!=li[i].v){ flag = true; } } if(flag){ printf("NO\n"); } else { printf("YES\n"); Task(1,1,n); printf("\n"); } } return 0; }