题意:
构造出一个序列,满足下面m个要求:
每一个要求的组成是l,r,q三个数,表示从a[l]&a[l+1]....&a[r]的值为q,问能不能构造出这样的序列。
思路:
sum[i]表示该区间的&的值,一开始处理每个要求的时候,我们都让它直接满足该要求,sum[i]|q来满足。最后我们再看看每个sum[i]的值是否还为原来的值,如果不是,则无法构造。可以的话,那么我们查询到叶子节点就是构造的序列。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=1e5+5;
int sum[maxn<<2],lazy[maxn<<2];
int l[maxn],r[maxn],c[maxn];
int now;
void pushdown(int i)
{
if(lazy[i])
{
sum[2*i]|=lazy[i];
sum[2*i+1]|=lazy[i];
lazy[2*i]|=lazy[i];
lazy[2*i+1]|=lazy[i];
lazy[i]=0;
}
}
void update(int i,int l,int r,int x,int y,int c)
{
if(x<=l&&r<=y)
{
sum[i]|=c;
lazy[i]|=c;
return;
}
pushdown(i);
int mid=(l+r)/2;
if(x<=mid) update(2*i,l,mid,x,y,c);
if(y>mid) update(2*i+1,mid+1,r,x,y,c);
sum[i]=sum[2*i]&sum[2*i+1];
return;
}
void query(int i,int l,int r,int x,int y)
{
if(x<=l&&r<=y)
{
now&=sum[i];
return;
}
pushdown(i);
int mid=(l+r)/2;
if(x<=mid) query(2*i,l,mid,x,y);
if(y>mid) query(2*i+1,mid+1,r,x,y);
sum[i]=sum[2*i]&sum[2*i+1];
return;
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m))
{
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&l[i],&r[i],&c[i]);
update(1,1,n,l[i],r[i],c[i]);
}
for(int i=1;i<=m;i++)
{
now=(1<<30)-1;
query(1,1,n,l[i],r[i]);
if(now!=c[i])
{
cout<<"NO"<<endl;
return 0;
}
}
cout<<"YES"<<endl;
for(int i=1;i<=n;i++)
{
now=(1<<30)-1;
query(1,1,n,i,i);
cout<<now<<" ";
}
}
return 0;
}