D. Interesting Array
题意:一个长度为n的序列,有m个要求,对于每个要求给出li,ri,qi,意味着序列中从li到ri这个区间内的所有值与运算后得到qi,问这样的序列是否存在,如果存在,输出任意可行序列。
思路:线段树(区间更新)。节点存的是相应区间内所有数“与”起来的值,对每个要求mi,为对应区间“或”上qi,最后再对每个要求查询一次,看是否满足。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<math.h>
using namespace std;
#define maxn 100010
#define ll long long
struct node{
ll val,add;
int l,r;
};
node tree[maxn<<2];
void build_tree(int n,int l,int r){
tree[n].l=l; tree[n].r=r;
tree[n].val=tree[n].add=0LL;
if(l==r)return;
int mid=(l+r)>>1;
build_tree(n<<1,l,mid);
build_tree((n<<1)|1,mid+1,r);
}
void push_down(int x){
tree[x<<1].val|=tree[x].add;
tree[(x<<1)|1].val|=tree[x].add;
tree[x<<1].add|=tree[x].add;
tree[(x<<1)|1].add|=tree[x].add;
tree[x].add=0LL;
}
void push_up(int x){
tree[x].val=tree[x<<1].val&tree[(x<<1)|1].val;
}
void update(int n,int l,int r,ll v){
if(tree[n].l==l&&tree[n].r==r){
tree[n].val|=v;
tree[n].add|=v;
return;
}
if(tree[n].add)push_down(n);
int mid=(tree[n].l+tree[n].r)>>1;
if(r<=mid){
update(n<<1,l,r,v);
}else{
if(l>mid){
update((n<<1)|1,l,r,v);
}else{
update(n<<1,l,mid,v);
update((n<<1)|1,mid+1,r,v);
}
}
push_up(n);
}
ll query(int n,int l,int r){
if(tree[n].l==l&&tree[n].r==r){
return tree[n].val;
}
if(tree[n].add)push_down(n);
int mid=(tree[n].l+tree[n].r)>>1;
if(r<=mid){
return query(n<<1,l,r);
}else{
if(l>mid){
return query((n<<1)|1,l,r);
}else{
return query(n<<1,l,mid)&query((n<<1)|1,mid+1,r);
}
}
}
int ql[maxn];
int qr[maxn];
ll qq[maxn];
int main(){
int n,m;
while(cin>>n>>m){
build_tree(1,1,n);
for(int i=1;i<=m;i++){
scanf("%d%d%I64d",&ql[i],&qr[i],&qq[i]);
update(1,ql[i],qr[i],qq[i]);
}
bool ok=1;
for(int i=1;i<=m;i++){
if(query(1,ql[i],qr[i])!=qq[i]){
ok=0;break;
}
}
if(ok){
printf("YES\n");
for(int i=1;i<=n;i++){
printf("%I64d ",query(1,i,i));
}
}else{
printf("NO\n");
}
}
return 0;
}