题目
大暴力。
用线段树维护区间最大值,区间或,区间与和标记。
如果当前修改对于当前区间或和区间与的贡献是一样的,那么说明这个修改对当前区间所有数贡献都一样。那么我们就打个区间加标记。否则往下递归。
根据势能分析这个东西的复杂度是(O(nlog^2n))的(认为(n,m,a)同阶)。
证明我肯定不会啊。
#include<bits/stdc++.h>
using namespace std;
namespace IO
{
char ibuf[(1<<21)+1],obuf[(1<<21)+1],st[11],*iS,*iT,*oS=obuf,*oT=obuf+(1<<21);
char Get(){return (iS==iT? (iT=(iS=ibuf)+fread(ibuf,1,(1<<21)+1,stdin),(iS==iT? EOF:*iS++)):*iS++);}
void Flush(){fwrite(obuf,1,oS-obuf,stdout),oS=obuf;}
void Put(char x){*oS++=x;if(oS==oT)Flush();}
int read(){int x=0,c=Get();while(!isdigit(c))c=Get();while(isdigit(c))x=x*10+c-48,c=Get();return x;}
void write(int x){int top=0;if(!x)Put('0');while(x)st[++top]=(x%10)+48,x/=10;while(top)Put(st[top--]);Put('
');}
}
using namespace IO;
int max(int a,int b){return a>b? a:b;}
const int N=200007;
int n,m,AND[N<<2],OR[N<<2],mx[N<<2],tag[N<<2];
#define ls p<<1
#define rs p<<1|1
#define mid ((l+r)>>1)
void pushup(int p){AND[p]=AND[ls]&AND[rs],OR[p]=OR[ls]|OR[rs],mx[p]=max(mx[ls],mx[rs]);}
void modify(int p,int v){tag[p]+=v,AND[p]+=v,OR[p]+=v,mx[p]+=v;}
void pushdown(int p){modify(ls,tag[p]),modify(rs,tag[p]),tag[p]=0;}
void build(int p,int l,int r)
{
if(l==r) return (void)(AND[p]=OR[p]=mx[p]=read());
build(ls,l,mid),build(rs,mid+1,r),pushup(p);
}
void update_and(int p,int l,int r,int L,int R,int x)
{
if(tag[p]&&l<r) pushdown(p);
if((OR[p]&x)==OR[p]) return ;
if(L<=l&&r<=R&&AND[p]-(AND[p]&x)==OR[p]-(OR[p]&x)) return modify(p,(AND[p]&x)-AND[p]);
if(L<=mid) update_and(ls,l,mid,L,R,x);
if(R>mid) update_and(rs,mid+1,r,L,R,x);
pushup(p);
}
void update_or(int p,int l,int r,int L,int R,int x)
{
if(tag[p]&&l<r) pushdown(p);
if((AND[p]|x)==AND[p]) return ;
if(L<=l&&r<=R&&(AND[p]|x)-AND[p]==(OR[p]|x)-OR[p]) return modify(p,(AND[p]|x)-AND[p]);
if(L<=mid) update_or(ls,l,mid,L,R,x);
if(R>mid) update_or(rs,mid+1,r,L,R,x);
pushup(p);
}
int query(int p,int l,int r,int L,int R)
{
if(tag[p]&&l<r) pushdown(p);
if(L<=l&&r<=R) return mx[p];
return max((L<=mid? query(ls,l,mid,L,R):0),(R>mid? query(rs,mid+1,r,L,R):0));
}
int main()
{
n=read(),m=read(),build(1,1,n);
for(int l,r,x;m;--m)
switch(read())
{
case 1:l=read(),r=read(),x=read(),update_and(1,1,n,l,r,x);break;
case 2:l=read(),r=read(),x=read(),update_or(1,1,n,l,r,x);break;
case 3:l=read(),r=read(),write(query(1,1,n,l,r));break;
}
return Flush(),0;
}