or SPJ
这个题目名称好奇怪啊。
link
构造一个长度为n的非负整数序列x,满足m个条件,第i个条件为x[li]|x[li+1]|…|x[ri]=pi。
一道比较巧妙的按位线段树题目。首先可以考虑当前位运算(也就是或)的特点,发现若区间内所有数的某一位均为0,那么答案的那一位才是0,否则就是1。于是可以考虑按位开线段树,优先满足0的那些位(把区间内的数那一位全部赋值为0),然后在做完这些事之后把其它位都赋值为1,毕竟如果这样都没法保证那些“1位”的利益那么其它方法就更别提了。最后检测一下这样构造出来的序列是否符合题意即可。
线段树只是一个辅助作用。
#include
#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<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