1. 程式人生 > >牛客練習賽29E 位運算?位運算! splay

牛客練習賽29E 位運算?位運算! splay

Description

請實現一個數據結構支援以下操作: 區間迴圈左右移,區間與,區間或,區間求和。

所有操作形如 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 一些說明:

  1. 對於00000000000000000101,右移一位後會變成10000000000000000010
  2. 不是區間位移,是區間中的每一個數的二進位制位的位移

Solution

心態崩了,splay的做法常數昇天,調不出來打出gg

考慮套路做法。我們把二進位制的每一位單獨處理,區間&和|就按位討論,區間求和就是統計每一位上1的數量*這一位貢獻的和,區間左右移就是依次交換這些區間 注意到1、2操作的特殊性,我們可以 (不可以) 用splay維護20個區間,每次交換就切出來貼在目標位置上。這樣做理論上是nlog^2n的

然鵝,然鵝我的程式碼常數巨大,2e5的資料要跑15s。人生幾何,不如寫一些不那麼噁心的題目。。

Code

#include <stdio.h>
#include
<string.h>
#include <bitset> #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; }