看到区间修改和区间查询操作时,立马想到了线段树,这题确实可以用线段树做,因为一个数A或运算他自己的结果还是A(即A|A=A)所以区间修改操作时可以直接把所在的区间改成X,代码代码如下
if(l<=L[x]&&r>=R[x]){ sum[x]=data; return; }
此外与正常线段树并无太大差距了,代码如下
#include<bits/stdc++.h> using namespace std; const int maxn=1000001; int n,m,a[maxn],L[maxn<<2],R[maxn<<2],sum[maxn<<2],tag[maxn<<2],ans; void bulid(int x,int l,int r){ L[x]=l,R[x]=r; if(l==r){ sum[x]=a[l]; return; } int mid=l+r>>1; bulid(x<<1,l,mid); bulid(x<<1|1,mid+1,r); sum[x]=sum[x<<1]|sum[x<<1|1]; } void pushdown(int x,int data){ tag[x]=data; sum[x]=data; } void updata(int x,int l,int r,int data){ if(r<L[x]||l>R[x]){ return; } if(l<=L[x]&&r>=R[x]){ sum[x]=data; tag[x]=data; return; } if(tag[x]){ pushdown(x<<1,tag[x]); pushdown(x<<1|1,tag[x]); tag[x]=0; } updata(x<<1,l,r,data); updata(x<<1|1,l,r,data); sum[x]=sum[x<<1]|sum[x<<1|1]; } void getsum(int x,int l,int r){ if(r<L[x]||l>R[x]){ return; } if(l<=L[x]&&r>=R[x]){ ans|=sum[x]; return; } if(tag[x]){ pushdown(x<<1,tag[x]); pushdown(x<<1|1,tag[x]); tag[x]=0; } getsum(x<<1,l,r); getsum(x<<1|1,l,r); } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); } bulid(1,1,n); for(int i=1;i<=m;i++){ int op; scanf("%d",&op); if(op==1){ int l,r; scanf("%d%d",&l,&r); ans=0; getsum(1,l,r); printf("%d\n",ans); }else{ int l,r,k; scanf("%d%d%d",&l,&r,&k); updata(1,l,r,k); } } return 0; }