请实现一个数据结构支持以下操作:
区间循环左右移,区间与,区间或,区间求和。
所有操作形如 opt l r v。
opt=1 表示将区间[l,r]循环右移v位。
opt=2 表示将区间[l,r]循环左移v位。
opt=3 表示将区间[l,r]按位或上v。
opt=4 表示将区间[l,r]按位与上v。
opt=5 询问区间[l,r]的和。
保证opt=1或2时 1 ≤ v ≤ 20
注意:为了优化你的做题体验,操作5也会输入一个v,但是是没有意义的。
注意:循环左右移在20个二进制位的意义下进行
1 ≤ N,Q ≤ 2*105 0 ≤ ai < 220
一些说明:
心态崩了,splay的做法常数升天,调不出来打出gg
考虑套路做法。我们把二进制的每一位单独处理,区间&和|就按位讨论,区间求和就是统计每一位上1的数量*这一位贡献的和,区间左右移就是依次交换这些区间
注意到1、2操作的特殊性,我们可以 (不可以) 用splay维护20个区间,每次交换就切出来贴在目标位置上。这样做理论上是nlog^2n的
然鹅,然鹅我的代码常数巨大,2e5的数据要跑15s。人生几何,不如写一些不那么恶心的题目。。
#include
#include
#include
#define rep(i,st,ed) for (register int i=st,_=ed;i<=_;++i)
#define drp(i,st,ed) for (register int i=st,_=ed;i>=_;--i)
typedef long long LL;
const int N=200005;
struct treeNode {
int son[2],fa,size,tag,sum,val;
} t[N*22];
int a[N],root[21],last[21];
int w[N],wjp;
LL bin[N];
int read() {
int x=0,v=1; char ch=getchar();
for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());
for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
return x*v;
}
void push_up(int x) {
if (!x) return ;
t[x].size=t[t[x].son[0]].size+t[t[x].son[1]].size+1;
t[x].sum=t[x].val+t[t[x].son[0]].sum+t[t[x].son[1]].sum;
}
void push_down(int x) {
if (t[x].tag==-1) return ;
int w=t[x].tag; t[x].tag=-1;
if (t[x].son[0]) {
t[t[x].son[0]].tag=t[t[x].son[0]].val=w;
t[t[x].son[0]].sum=t[t[x].son[0]].size*w;
}
if (t[x].son[1]) {
t[t[x].son[1]].tag=t[t[x].son[1]].val=w;
t[t[x].son[1]].sum=t[t[x].son[1]].size*w;
}
}
void rotate(int x) {
int y=t[x].fa; int z=t[y].fa;
int k=t[y].son[1]==x;
t[z].son[t[z].son[1]==y]=x; t[x].fa=z;
t[y].son[k]=t[x].son[!k]; t[t[x].son[!k]].fa=y;
t[x].son[!k]=y; t[y].fa=x;
push_up(y); push_up(x);
}
void splay(int &root,int x,int goal=0) {
for (;t[x].fa!=goal;) {
int y=t[x].fa; int z=t[y].fa;
if (z!=goal) {
if ((t[y].son[1]==x)^(t[z].son[1]==y)) rotate(x);
else rotate(y);
}
rotate(x);
}
if (!goal) root=x;
}
int kth(int root,int k) {
int x=root;
for (;233;) {
push_down(x);
if (t[t[x].son[0]].size+1==k) return x;
if (t[t[x].son[0]].size>=k) x=t[x].son[0];
else {
k-=t[t[x].son[0]].size+1;
x=t[x].son[1];
}
}
}
int cut(int &root,int l,int r) {
int L=kth(root,l-1);
int R=kth(root,r+1);
splay(root,L); splay(root,R,root);
int ret=t[R].son[0];
t[ret].fa=t[R].son[0]=0;
push_up(R); push_up(L);
return ret;
}
int build(int l,int r) {
int mid=(l+r)>>1;
int pos=mid+wjp;
t[pos].tag=-1;
t[pos].size=1;
t[pos].val=w[mid-1];
if (l<mid) {
t[pos].son[0]=build(l,mid-1);
t[t[pos].son[0]].fa=pos;
}
if (mid<r) {
t[pos].son[1]=build(mid+1,r);
t[t[pos].son[1]].fa=pos;
}
push_up(pos);
return pos;
}
int main(void) {
freopen("data.in","r",stdin);
freopen("myp.out","w",stdout);
int n=read(),q=read();
rep(i,1,n) a[i]=read();
bin[0]=1; rep(i,1,19) bin[i]=bin[i-1]*2;
rep(j,0,19) {
rep(i,1,n) w[i]=(a[i]&bin[j])!=0;
root[j]=build(1,n+2);
wjp+=n+2;
}
for (;q--;) {
int opt=read(),l=read(),r=read(),v=read();
if (opt==2) {
rep(i,0,v-1) last[i]=cut(root[i],l+1,r+1);
rep(i,v,19) {
int rt=root[i];
int now=cut(rt,l+1,r+1);
t[t[rt].son[1]].son[0]=last[i-v];
t[last[i-v]].fa=t[rt].son[1];
push_up(t[rt].son[1]); push_up(rt);
last[i]=now; root[i]=rt;
}
rep(i,0,v-1) {
int rt=root[i];
t[t[rt].son[1]].son[0]=last[i+20-v];
t[last[i+20-v]].fa=t[rt].son[1];
push_up(t[rt].son[1]); push_up(rt);
root[i]=rt;
}
} else if (opt==1) {
drp(i,19,20-v) last[i]=cut(root[i],l+1,r+1);
drp(i,19-v,0) {
int rt=root[i];
int now=cut(rt,l+1,r+1);
int rs=t[rt].son[1];
t[t[rt].son[1]].son[0]=last[i+v];
t[last[i+v]].fa=t[rt].son[1];
push_up(t[rt].son[1]); push_up(rt);
last[i]=now; root[i]=rt;
}
drp(i,19,20-v) {
int rt=root[i]; int rs=t[rt].son[1];
t[rs].son[0]=last[i-20+v];
t[last[i-20+v]].fa=rs;
push_up(rs); push_up(rt);
root[i]=rt;
}
} else if (opt==3) {
rep(i,0,19) if (v&bin[i]) {
int rt=root[i];
splay(rt,kth(rt,l));
splay(rt,kth(rt,r+2),rt);
int tmp=t[t[rt].son[1]].son[0];
t[tmp].tag=t[tmp].val=1;
t[tmp].sum=t[tmp].size;
push_up(t[rt].son[1]); push_up(rt);
root[i]=rt;
}
} else if (opt==4) {
rep(i,0,19) if (!(v&bin[i])) {
int rt=root[i];
splay(rt,kth(rt,l));
splay(rt,kth(rt,r+2),rt);
int rs=t[rt].son[1];
int tmp=t[rs].son[0];
t[tmp].tag=t[tmp].val=t[tmp].sum=0;
push_up(rs); push_up(rt);
root[i]=rt;
}
} else {
LL ans=0;
rep(i,0,19) {
int rt=root[i];
splay(rt,kth(rt,l));
splay(rt,kth(rt,r+2),rt);
ans+=bin[i]*t[t[t[rt].son[1]].son[0]].sum;
root[i]=rt;
}
printf("%lld\n", ans);
}
}
return 0;
}