另一元宵节 线段树
Posted anyixing-fly
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了另一元宵节 线段树相关的知识,希望对你有一定的参考价值。
其实最开始这个题我没做出来是因为我不知道&是啥意思,我以为是加和
这个题的意思其实就是让构建一个数组,使它的某个区间按位与的和为一个数,看看会不会产生矛盾。
知道这一点后就好办了,新建一个为0的数组,每次查询就 | 一下,然后查询区间按位与的和,看看符不符合]
为什么要 | 呢?
这要考虑&是怎么运算的了
在二进制位下,只有两个数字的某一位上都是1,&出来才是1,所以也有一个很显然的问题,&出来的数不一定与区间内的每一个数相等
但他们的二进制位下,&出来的数的二进制位一定相等,所以每次查询的时候把要查询的那个数对应的二进制位 | 一下就行了
然后就是线段树的板子吧,这里不能用树状数组,想想为什么
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int N=1e6+10; 6 typedef long long ll; 7 ll tree[N],lazy[N]; 8 void updata(int rt,int l,int r,ll w){ 9 tree[rt]=tree[rt]|w; 10 lazy[rt]=tree[rt]|w; 11 } 12 void pushdown(int rt,int l,int r){ 13 int mid=l+r>>1; 14 updata(rt<<1,l,mid,lazy[rt]); 15 updata(rt<<1|1,mid+1,r,lazy[rt]); 16 lazy[rt]=0; 17 } 18 void modify(int rt,int l,int r,int s,int t,ll w){ 19 if(s<=l&&r<=t){ 20 updata(rt,l,r,w); 21 return; 22 } 23 pushdown(rt,l,r); 24 int mid=l+r>>1; 25 if(s<=mid)modify(rt<<1,l,mid,s,t,w); 26 if(t>mid)modify(rt<<1|1,mid+1,r,s,t,w); 27 tree[rt]=tree[rt<<1]&tree[rt<<1|1]; 28 } 29 ll query(int rt,int l,int r,int s,int t){ 30 if(s<=l&&t>=r)return tree[rt]; 31 pushdown(rt,l,r); 32 int mid=l+r>>1; 33 if(t<=mid)return query(rt<<1,l,mid,s,t); 34 else if(s>mid)return query(rt<<1|1,mid+1,r,s,t); 35 else return query(rt<<1,l,mid,s,t)&query(rt<<1|1,mid+1,r,s,t); 36 } 37 int main(){ 38 int m,n,t;bool flag; 39 freopen("kuai.in","r",stdin); 40 freopen("kuai.out","w",stdout); 41 scanf("%d",&t); 42 while(t--){ 43 flag=1; 44 memset(tree,0,sizeof(tree)); 45 scanf("%d%d",&n,&m); 46 for(int i=1;i<=m;i++){ 47 int l,r; 48 ll w; 49 scanf("%d%d%lld",&l,&r,&w); 50 modify(1,1,n,l,r,w); 51 ll data=query(1,1,n,l,r); 52 if(data!=w)flag=0; 53 } 54 if(flag)printf("YES "); 55 else printf("NO "); 56 } 57 return 0; 58 }
以上是关于另一元宵节 线段树的主要内容,如果未能解决你的问题,请参考以下文章