看到区间修改和区间查询操作时,立马想到了线段树,这题确实可以用线段树做,因为一个数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;
}



京公网安备 11010502036488号