or SPJ
这个题目名称好奇怪啊。
构造一个长度为n的非负整数序列x,满足m个条件,第i个条件为x[li]|x[li+1]|…|x[ri]=pi。
一道比较巧妙的按位线段树题目。首先可以考虑当前位运算(也就是或)的特点,发现若区间内所有数的某一位均为0,那么答案的那一位才是0,否则就是1。于是可以考虑按位开线段树,优先满足0的那些位(把区间内的数那一位全部赋值为0),然后在做完这些事之后把其它位都赋值为1,毕竟如果这样都没法保证那些“1位”的利益那么其它方法就更别提了。最后检测一下这样构造出来的序列是否符合题意即可。
线段树只是一个辅助作用。
#include<cstdio>
#define zczc
const int N=100010;
const int S=30;
inline void read(int &wh){
wh=0;int f=1;char w=getchar();
while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
while(w<='9'&&w>='0'){wh=wh*10+w-'0';w=getchar();}
wh*=f;return;
}
int m,n,an[N];
#define lc (wh<<1)
#define rc (wh<<1|1)
#define mid (t[wh].l+t[wh].r>>1)
#define num (t[wh].r-t[wh].l+1)
struct tree{
struct node{
int l,r;
bool all;
}t[N<<2];
inline void build(int wh,int l,int r){
t[wh].l=l,t[wh].r=r;
if(l==r)return;
build(lc,l,mid);
build(rc,mid+1,r);
}
inline void change(int wh,int wl,int wr){
if(t[wh].all)return;
if(wl<=t[wh].l&&t[wh].r<=wr){t[wh].all=true;return;}
if(wl<=mid)change(lc,wl,wr);
if(wr>mid)change(rc,wl,wr);
t[wh].all=t[lc].all&&t[rc].all;
}
inline void visit(int wh,int pl){
if(t[wh].all)return;
if(t[wh].l==t[wh].r){
an[t[wh].l]|=(1<<pl);
return;
}
visit(lc,pl);
visit(rc,pl);
}
}tr[S];
struct no{
int l,r,data;
}t[N<<2];
inline void build(int wh,int l,int r){
t[wh].l=l,t[wh].r=r;
if(l==r){
t[wh].data=an[l];return;
}
build(lc,l,mid);
build(rc,mid+1,r);
t[wh].data=t[lc].data|t[rc].data;
}
inline int work(int wh,int wl,int wr){
if(wl<=t[wh].l&&t[wh].r<=wr)return t[wh].data;
int an=0;
if(wl<=mid)an|=work(lc,wl,wr);
if(wr>mid)an|=work(rc,wl,wr);
return an;
}
#undef lc
#undef rc
#undef mid
#undef num
struct node{
int l,r,data;
}a[N];
signed main(){
#ifdef zczc
freopen("in.txt","r",stdin);
#endif
read(m);read(n);
for(int i=0;i<S;i++)tr[i].build(1,1,m);
for(int i=1;i<=n;i++){
read(a[i].l);read(a[i].r);read(a[i].data);
for(int j=0;j<S;j++){
if(a[i].data&(1<<j))continue;
tr[j].change(1,a[i].l,a[i].r);
}
}
for(int i=0;i<S;i++)tr[i].visit(1,i);
build(1,1,m);
for(int i=1;i<=n;i++){
if(work(1,a[i].l,a[i].r)!=a[i].data){
printf("No");return 0;
}
}
printf("Yes\n");
for(int i=1;i<=m;i++)printf("%d ",an[i]);
return 0;
}
一如既往,万事胜意