题目链接:Interesting Array


题目大意:题目要我们构造一个序列,满足m个条件,m个区间的与值为x,问我们是否能够构造出来,若不能输出NO,若可以则输出YES并输出,构造出的序列。


一道线段树好题。这道题我们要用到与运算的性质。要让我们当前区间的区间与为x,那么我们可以想到,我们区间的每个数字的每一位(二进制每一位),若x在这一位有1,那么区间所有数字都必须为1.因为只要有一个不是1,那么这一位就不会有1了,然后就不会等于x。怎么让每个数字的每一位与x相等呢?我们让区间每个数字或运算上x即可。所以我们最后计算每个需要满足的区间是否为需要满足的值即可。


AC代码:

#pragma GCC optimize(2)
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=1e5+10;
int n,m,l[N],r[N],x[N],flag;
struct node{
	int l,r,sum,lazy;
}t[N<<2];
inline void push_up(int p){
	t[p].sum=t[p<<1].sum&t[p<<1|1].sum;
}
inline void push_down(int p){
	if(t[p].lazy){
		t[p<<1].sum|=t[p].lazy;	t[p<<1|1].sum|=t[p].lazy;
		t[p<<1].lazy|=t[p].lazy; t[p<<1|1].lazy|=t[p].lazy;
		t[p].lazy=0;
	}
}
void build(int p,int l,int r){
	t[p].l=l;	t[p].r=r;
	if(l==r)	return ;	int mid=l+r>>1;
	build(p<<1,l,mid);	build(p<<1|1,mid+1,r);
}
void change(int p,int l,int r,int x){
	if(t[p].l==l&&t[p].r==r){
		t[p].sum|=x;	t[p].lazy|=x;	return ;
	}
	push_down(p);	int mid=t[p].l+t[p].r>>1;
	if(r<=mid)	change(p<<1,l,r,x);
	else if(l>mid)	change(p<<1|1,l,r,x);
	else	change(p<<1,l,mid,x),change(p<<1|1,mid+1,r,x);
	push_up(p);
}
int ask(int p,int l,int r){
	if(t[p].l==l&&t[p].r==r)	return t[p].sum;
	push_down(p);	int mid=t[p].l+t[p].r>>1;
	if(r<=mid)	return ask(p<<1,l,r);
	else if(l>mid)	return ask(p<<1|1,l,r);
	else	return ask(p<<1,l,mid)&ask(p<<1|1,mid+1,r);
}
int out(int p,int x){
	if(t[p].l==t[p].r)	return t[p].sum;
	push_down(p);	int mid=t[p].l+t[p].r>>1;
	if(x<=mid)	return out(p<<1,x);
	else	return out(p<<1|1,x);
}
signed main(){
	scanf("%d %d",&n,&m);	build(1,1,n);
	for(int i=1;i<=m;i++){
		scanf("%d %d %d",&l[i],&r[i],&x[i]);
		change(1,l[i],r[i],x[i]);
	}
	for(int i=1;i<=m&&!flag;i++){
		if(ask(1,l[i],r[i])!=x[i])	flag++;
	}
	if(flag)	return puts("NO"),0;	puts("YES");
	for(int i=1;i<=n;i++)	printf("%d ",out(1,i));puts("");
	return 0;
}