由于是循环移位,所以不用担心越界的情况
在&,|的时候考虑一下相关的性质:
&:该位为1,则没有影响,为0,就全部置0
|:和&刚好相反
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#include <bits/stdc++.h>
#define inf 0x7fffffff
//#define ll long long
#define int long long
//#define double long double
#define re int
#define void inline void
#define eps 1e-8
//#define mod 1e9+7
#define ls(p) p<<1
#define rs(p) p<<1|1
#define pi acos(-1.0)
#define pb push_back
#define P pair < int , int >
#define mk make_pair
using namespace std;
const int mod=1e9+7;
const int M=1e8+5;
const int N=8e5+5;//?????????? 4e8
struct nod
{
int sum[25],add;
}e[N];
int n,m;
int b[N];
void push(int p)
{
for(re i=0;i<20;i++) e[p].sum[i]=e[ls(p)].sum[i]+e[rs(p)].sum[i];
}
void bulid(int p,int l,int r)
{
if(l==r)
{
int x;
scanf("%lld",&x);
for(re i=0;i<20;i++) if((1<<i)&x) e[p].sum[i]=1;
return;
}
int mid=(l+r)>>1;
bulid(ls(p),l,mid);bulid(rs(p),mid+1,r);
push(p);
}
void rotate(int p,int len)
{
for(re i=0;i<20;i++) b[i]=e[p].sum[(i+len)%20];
for(re i=0;i<20;i++) e[p].sum[i]=b[i];
e[p].add+=len;
e[p].add%=20;
}
void spread(int p,int l,int r)
{
if(e[p].add)
{
rotate(ls(p),e[p].add);
rotate(rs(p),e[p].add);
e[p].add=0;
}
int mid=(l+r)>>1;
for(re i=0;i<20;i++)
{
if(e[p].sum[i]==0) e[ls(p)].sum[i]=e[rs(p)].sum[i]=0;
else if(e[p].sum[i]==r-l+1) {e[ls(p)].sum[i]=mid-l+1,e[rs(p)].sum[i]=r-mid;}
}
}
void update(int p,int L,int R,int l,int r,int v,int op)
{
if(L<=l&&r<=R)
{
if(op==1) rotate(p,v);
else if(op==2) rotate(p,20-v);
else if(op==3)
{
for(re i=0;i<20;i++) if(((v>>i)&1)) e[p].sum[i]=r-l+1;
}
else
{
for(re i=0;i<20;i++) if(!((v>>i)&1)) e[p].sum[i]=0;
}
return;
}
spread(p,l,r);
int mid=(l+r)>>1;
if(L<=mid) update(ls(p),L,R,l,mid,v,op);
if(mid<R) update(rs(p),L,R,mid+1,r,v,op);
push(p);
}
int ask(int p,int id,int L,int R,int l,int r)
{
if(L<=l&&r<=R) return e[p].sum[id];
spread(p,l,r);
int mid=(l+r)>>1;
int ans=0;
if(L<=mid) ans+=ask(ls(p),id,L,R,l,mid);
if(mid<R) ans+=ask(rs(p),id,L,R,mid+1,r);
return ans;
}
void solve()
{
cin>>n>>m;
bulid(1,1,n);
while(m--)
{
int op,l,r,x;
scanf("%lld%lld%lld%lld",&op,&l,&r,&x);
if(op<5) update(1,l,r,1,n,x,op);
else
{
int ans=0;
for(re i=0;i<20;i++) ans+=(ask(1,i,l,r,1,n)*(1<<i));
printf("%lld\n",ans);
}
}
}
signed main()
{
int T=1;
// cin>>T;
for(int index=1;index<=T;index++)
{
// printf("Case %d:\n",index);
solve();
// puts("");
}
return 0;
}
/*
1
6 5
0 0 0 122 499 8888
*/