题面
【题目描述】
你需要构造一个长度为 n 的数列 X,当中的数字范围从 0 到 2^30-1。除此之外你需要
满足 m 个条件,第 i 个条件为 X[li]|X[li+1]|……|X[ri]=pi。|为按位或运算。
【输入描述】
第一行输入两个整数 n,m
接下来的 m 行每行输入三个整数 li,ri,pi
【输出描述】
如果存在这样的序列,第一行输出 Yes,否则输出 No。
如果存在这样的序列,第二行输出 n 个数,为数列 X。
【样例】
输入
2 1
1 2 1
输出
Yes
1 1
【数据范围】
对于 30%的数据,n,m<=1000。
对于另外 30%的数据,pi<=1。
对于 100%的数据,n,m<=100000,1<=li<=ri<=n,0<=pi<2^30。
题解
又是一道位运算的题目(感觉是最简单的一道……)
题意还是比较清楚的,这里不细说了。
"对于另外30%的数据",出题人在这里是不是给了一个小小的提示?
众所周知,位运算有一个性质,即对于每一个位是独立的,因此想到分开考虑每个位的情况。
对于每个条件的pi的每一位,如果这一位为0,那么这个区间内所有的数的这一位显然都为0。
因此想到如下做法:
先把数列内所有数设为230-1。
对于每个条件的pi的每一位,如果这一位为0,那么将该区间内所有数的这一位置0,最后判断每个条件是否成立即可。
用线段树维护数列,只需记录区间内所有数的或即可。复杂度O(mlog2n)
具体细节见代码。关于位运算的操作,这里不多说了。
代码
1 #include <stdio.h> 2 #define N 100010 3 #define reg register 4 const int pv=(1<<30)-1; 5 int n,m,l[N],r[N],a[N]; 6 struct node{int o,l;}t[270000]; 7 void build(int l,int r,int k) { 8 t[k].o=pv;t[k].l=0; 9 if(l!=r) { 10 build(l,l+r>>1,k<<1); 11 build((l+r>>1)+1,r,k<<1|1); 12 } 13 } 14 void pushdown(int k) { 15 reg int x=t[k].l; 16 t[k<<1].o&=~x; 17 t[k<<1].l|=x; 18 t[k<<1|1].o&=~x; 19 t[k<<1|1].l|=x; 20 t[k].l=0; 21 } 22 void setzero(int l,int r,int a,int b,int c,int k) { 23 if(l==a&&r==b) { 24 t[k].o&=~c;t[k].l|=c; 25 return; 26 } 27 pushdown(k); 28 reg int mid=l+r>>1; 29 if(b<=mid) setzero(l,mid,a,b,c,k<<1); 30 else if(a>mid) setzero(mid+1,r,a,b,c,k<<1|1); 31 else { 32 setzero(l,mid,a,mid,c,k<<1); 33 setzero(mid+1,r,mid+1,b,c,k<<1|1); 34 } 35 } 36 int query(int l,int r,int a,int b,int k) { 37 if(l==a&&r==b) return t[k].o; 38 pushdown(k); 39 reg int mid=l+r>>1; 40 if(b<=mid) return query(l,mid,a,b,k<<1); 41 else if(a>mid) return query(mid+1,r,a,b,k<<1|1); 42 else { 43 return query(l,mid,a,mid,k<<1)|query(mid+1,r,mid+1,b,k<<1|1); 44 } 45 } 46 void output(int l,int r,int k) { 47 if(l==r) { 48 printf("%d ",t[k].o); 49 return; 50 } 51 pushdown(k); 52 output(l,l+r>>1,k<<1); 53 output((l+r>>1)+1,r,k<<1|1); 54 } 55 int main() { 56 scanf("%d%d",&n,&m); 57 build(1,n,1); 58 for(int i=0;i<m;++i) { 59 scanf("%d%d%d",l+i,r+i,a+i); 60 setzero(1,n,l[i],r[i],~a[i],1); 61 } 62 for(int i=0;i<m;++i) { 63 if(query(1,n,l[i],r[i],1)!=a[i]) { 64 puts("No"); 65 return 0; 66 } 67 } 68 puts("Yes"); 69 output(1,n,1); 70 return 0; 71 }