or SPJ

这个题目名称好奇怪啊。

link

构造一个长度为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;
}
posted @ 2022-01-21 09:37  Feyn618  阅读(38)  评论(0编辑  收藏  举报