您的位置:首页 > 其它

无旋Treap——从入门到放弃

2017-09-22 15:53 393 查看

前言

已经是从入门到放弃的第四篇了。

但是本文并不打算给大家讲无旋Treap复杂度证明一类的。

很显然每次操作都是期望Olog(n)的

什么是Treap?

Treap=Tree+heap

其核心思想在于在权值上维护一棵二叉查找树,在优先级上维护一个堆

有旋treap利用旋转操作来维护堆的性质,

而无旋treap利用有序构树维护堆的性质。

无旋Treap的两大构树顺序:权值与原排列

权值构树是很常见的一种构树方法。和有旋treap一样,左儿子与右儿子分别表示比自己小或比自己大的树,同时其优先级均低于该节点。这类问题用有旋treap也能够很好地解决。这样的题有很多,比如bzoj3224普通平衡树

但很不幸的是,很多与平衡树沾边的题目大多有维护一个原有有序序列的要求,这个要求基本上就把有旋treap干掉了。但是对于无旋treap,我们可以按原有的序列进行构树,这样就可以维护一个原有的有序排列了。

无旋treap的核心操作:split与merge

但是在构树之后肯定是有修改操作的。这点是毋庸置疑的。对于有旋treap,我们可以通过旋转来插入要加入的权值或是删除对应的节点,但对于可能需要进行区间操作的无旋treap,我们显然不能直接这样做。

此时,因为无旋treap的有序性,我们可以像一般的有旋treap一样对需要

插入/删除的部分进行定位查找。

如果是对于权值有序,像普通的有旋treap一样直接递归查找即可,

如果是对于原序列有序,则维护一组指针,也可以很方便地进行查询。

那么在查询到了相应的树中位置之后,我们需要做的就是——

把这棵树拆开

split

整个无旋treap的核心就是它的有序性。

在找到了需要操作的位置后,我们可以把这棵树拆成两棵有序的树。

对于查询到的节点,我们根据该节点左儿子的大小对这个节点应该在哪棵树进行判断,然后递归处理即可。

inline D split(Treap* pos,int k){
if(pos==NULL) return D(NULL,NULL);
D y;
if(sze(pos->son[0])>=k){
y=split(pos->son[0],k);
pos->son[0]=y.second;
pos->update();
y.second=pos;
}else{
y=split(pos->son[1],k-1-sze(pos->son[0]));
pos->son[1]=y.first;
pos->update();
y.first=pos;
}
return y;
}


merge

在你进行了加入/删除操作之后,你发现你手上现在有两到三棵树了,自然我们需要将这些树合并。合并的具体操作也是递归处理,此时就可以维护无旋treap的堆性质。

但是需要注意的是,合并时两棵树的左右位置,维护的是整棵树的有序性。

inline Treap* merge(Treap* a,Treap* b){
if(!a) return b;
if(!b) return a;
if(a->weight<b->weight){
a->son[1]=merge(a->son[1],b);
a->update();
return a;
}else{
b->son[0]=merge(a,b->son[0]);
b->update();
return b;
}
}


水得如壶口瀑布一样的水题

(1)bzoj3224:普通平衡树

题面见链接 传送门

最简单最基础的权值排序外加单点修改查询

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<iomanip>
using namespace std;
inline int read(){
int i=0,f=1;
char ch;
for(ch=getchar();!isdigit(ch);ch=getchar())
if(ch=='-') f=-1;
for(;isdigit(ch);ch=getchar())
i=(i<<3)+(i<<1)+(ch^48);
return i*f;
}
int buf[1024];
inline void write(int x){
if(!x){putchar('0');return ;}
if(x<0){putchar('-');x=-x;}
while(x){buf[++buf[0]]=x%10,x/=10;}
while(buf[0]) putchar(buf[buf[0]--]+48);
return ;
}
struct Treap{
Treap* son[2];
int weight,sze,data;
Treap(int v){
sze=1,data=v;weight=rand();
son[1]=son[0]=NULL;
return ;
}
inline void update(){
sze=1+(son[0]!=NULL?son[0]->sze:0)+(son[1]!=NULL?son[1]->sze:0);
return ;
}
}*root;
typedef pair<Treap*,Treap*>D;
inline int sze(Treap* pos){
return pos?pos->sze:0;
}
int n,ord,x;
inline Treap* merge(Treap* a,Treap* b){ if(!a) return b; if(!b) return a; if(a->weight<b->weight){ a->son[1]=merge(a->son[1],b); a->update(); return a; }else{ b->son[0]=merge(a,b->son[0]); b->update(); return b; } }
inline D split(Treap* pos,int k){ if(pos==NULL) return D(NULL,NULL); D y; if(sze(pos->son[0])>=k){ y=split(pos->son[0],k); pos->son[0]=y.second; pos->update(); y.second=pos; }else{ y=split(pos->son[1],k-1-sze(pos->son[0])); pos->son[1]=y.first; pos->update(); y.first=pos; } return y; }
inline int getrank(Treap* pos,int x){
if(pos==NULL) return 0;
else return (pos->data>=x)?getrank(pos->son[0],x):getrank(pos->son[1],x)+1+sze(pos->son[0]);
}
inline int getkth(int k){
D x=split(root,k-1);
D y=split(x.second,1);
Treap* pos=y.first;
root=merge(x.first,merge(pos,y.second));
return pos==NULL?0:pos->data;
}
inline void insert(int d){
int k=getrank(root,d);
D x=split(root,k);
Treap* pos=new Treap(d);
root=merge(x.first,merge(pos,x.second));
return ;
}
inline void remove(int d){
int k=getrank(root,d);
D x=split(root,k);
D y=split(x.second,1);
root=merge(x.first,y.second);
return ;
}
signed main(){
n=read();
for(int i=1;i<=n;++i){
ord=read();x=read();
switch(ord){
case 1:insert(x);break;
case 2:remove(x);break;
case 3:write(getrank(root,x)+1);puts("");break;
case 4:write(getkth(x));puts("");break;
case 5:write(getkth(getrank(root,x)));puts("");break;
case 6:write(getkth(getrank(root,x+1)+1));puts("");break;
}
}
return 0;
}


(2)bzoj1503 郁闷的出纳员

题面依然见链接点这里

很明显你不能直接进行全局修改对伐。这个时候你需要打一个差分。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<iomanip>
using namespace std;
inline int read(){
int i=0,f=1;
char ch;
for(ch=getchar();!isdigit(ch);ch=getchar())
if(ch=='-') f=-1;
for(;isdigit(ch);ch=getchar())
i=(i<<3)+(i<<1)+(ch^48);
return i*f;
}
int buf[1024];
inline void write(int x){
if(!x){putchar('0');return ;}
if(x<0){putchar('-');x=-x;}
while(x){buf[++buf[0]]=x%10,x/=10;}
while(buf[0]) putchar(buf[buf[0]--]+48);
return ;
}
#define stan 11
struct Treap{
Treap* son[2];
int sze,val,weight;
Treap(){val=sze=0,weight=rand();son[1]=son[0]=NULL;}
inline void update(){
sze=1+son[0]->sze+son[1]->sze;
}
}*null=new Treap,*root=null;
typedef pair<Treap*,Treap*> D;
int m,mini,tmp=0,x,cnt;
char ord[stan];
inline Treap* newtreap(int x){
Treap* pos=new Treap();
pos->son[0]=pos->son[1]=null;
pos->sze=1;pos->val=x;
return pos;
}
inline Treap* merge(Treap* a,Treap* b){
if(a==null) return b;
if(b==null) return a;
if(a->weight<b->weight){
a->son[1]=merge(a->son[1],b);
a->update();
return a;
}else{
b->son[0]=merge(a,b->son[0]);
b->update();
return b;
}
}
inline D split(Treap* pos,int k){
if(pos==null) return D(null,null);
D y;
if(pos->son[0]->sze>=k){
y=split(pos->son[0],k);
pos->son[0]=y.second;
pos->update();
y.second=pos;
}else{
y=split(pos->son[1],k-1-pos->son[0]->sze);
pos->son[1]=y.first;
pos->update();
y.first=pos;
}
return y;
}
inline int getrank(Treap* pos,int x){
if(pos==null) return 0;
return (pos->val>=x)?getrank(pos->son[0],x):getrank(pos->son[1],x)+1+pos->son[0]->sze;
}
inline int getkth(int k){
D x=split(root,k-1);
D y=split(x.second,1);
Treap* pos=y.first;
root=merge(x.first,merge(pos,y.second));
return pos->val;
}
inline void insert(int d){
int k=getrank(root,d);
D x=split(root,k);
Treap* pos=newtreap(d);
root=merge(x.first,merge(pos,x.second));
return ;
}
inline void remove(){
D x=split(root,1);
root=x.second;
++cnt;
return ;
}
signed main(){
m=read();mini=read();
while(m--){
scanf("%s",ord);x=read();
switch(ord[0]){
case 'I':if(x>=mini) insert(x-tmp);break;
case 'F':{
if(root==null||root->sze<x)
puts("-1");
else{
write(getkth(root->sze-x+1)+tmp);
puts("");
}
break;
}
case 'A':tmp+=x;break;
case 'S':{
tmp-=x;
while(root!=null&&getkth(1)+tmp<mini)
remove();
break;
}
}
}
write(cnt);
return 0;
}


(3)bzoj3223文艺平衡树

题面照例见链接点我点我

基础的区间翻转操作,像线段树一样打标记即可

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<iomanip>
using namespace std;
inline int read(){
int i=0,f=1;
char ch;
for(ch=getchar();!isdigit(ch);ch=getchar())
if(ch=='-') f=-1;
for(;isdigit(ch);ch=getchar())
i=(i<<3)+(i<<1)+(ch^48);
return i*f;
}
int buf[1024];
inline void write(int x){
if(!x){putchar('0');return ;}
if(x<0){putchar('-');x=-x;}
while(x){buf[++buf[0]]=x%10,x/=10;}
while(buf[0]) putchar(buf[buf[0]--]+48);
return ;
}
#define stan 555555
struct Treap{
Treap* son[2];
int val,weight,sze;bool flip;
Treap(){
val=-999999999;sze=0;weight=rand();flip=false;
return ;
}
inline void update(){
sze=son[1]->sze+son[0]->sze+1;
return ;
}
}*null=new Treap(),*root=null,*stack[stan],*x,*last;
typedef pair<Treap*,Treap*> D;
int n,m,sta,en;
inline void maintain_flip(Treap* pos){
if(pos==null) return ;
pos->flip^=1;
return ;
}
inline void pushdown(Treap* pos){
if(pos==null) return ;
if(pos->flip){
pos->flip^=1;
maintain_flip(pos->son[0]);
maintain_flip(pos->son[1]);
swap(pos->son[0],pos->son[1]);
}
return ;
}
inline Treap* newtreap(int val){
Treap *pos=new Treap();
pos->son[1]=pos->son[0]=null;pos->weight=rand();
pos->val=val;pos->sze=1;pos->flip=0;
return pos;
}
inline Treap* merge(Treap* a,Treap* b){
if(a==null) return b;
if(b==null) return a;
pushdown(a);pushdown(b);
if(a->weight<b->weight){
a->son[1]=merge(a->son[1],b);
a->update();
return a;
}else{
b->son[0]=merge(a,b->son[0]);
b->update();
return b;
}
}
inline D split(Treap* pos,int k){
if(pos==null) return D(null,null);
D y;pushdown(pos);
if(pos->son[0]->sze>=k){
y=split(pos->son[0],k);
pos->son[0]=y.second;
pos->update();
y.second=pos;
}else{
y=split(pos->son[1],k-1-pos->son[0]->sze);
pos->son[1]=y.first;
pos->update();
y.first=pos;
}
return y;
}
inline Treap* build(){
int p=0;
for(int i=1;i<=n;++i){
x=newtreap(i);last=null;
while(p&&stack[p]->weight>x->weight){
stack[p]->update();
last=stack[p];
stack[p--]=null;
}
if(p) stack[p]->son[1]=x;
x->son[0]=last;stack[++p]=x;
}
while(p) stack[p--]->update();
return stack[1];
}
inline void reverse(){
sta=read();en=read();
D x=split(root,sta-1);
D y=split(x.second,en-sta+1);
maintain_flip(y.first);
root=merge(x.first,merge(y.first,y.second));
return ;
}
inline void write_in_order(Treap* pos){
if(pos==null) return;
pushdown(pos);
write_in_order(pos->son[0]);
write(pos->val);putchar(' ');
write_in_order(pos->son[1]);
return ;
}
signed main(){
n=read();m=read();
root=build();
while(m--) reverse();
write_in_order(root);
return 0;
}


(4)ZJOI2006书架

题面还是点链接吧http://www.lydsy.com/JudgeOnline/problem.php?id=1861

这个地方也是很正常的单点修改,不过注意一下合并的顺序即可

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<iomanip>
using namespace std;
inline int read(){
int i=0,f=1;
char ch;
for(ch=getchar();!isdigit(ch);ch=getchar())
if(ch=='-') f=-1;
for(;isdigit(ch);ch=getchar())
i=(i<<3)+(i<<1)+(ch^48);
return i*f;
}
int buf[1024];
inline void write(int x){
if(!x){putchar('0');return ;}
if(x<0){putchar('-');x=-x;}
while(x){buf[++buf[0]]=x%10,x/=10;}
while(buf[0]) putchar(buf[buf[0]--]+48);
return ;
}
typedef unsigned int uint;
inline uint nextUint() {
static uint seed = 19260817;
seed ^= seed << 13;
seed ^= seed >> 17;
seed ^= seed << 5;
return seed;
}
#define stan 88888
#define sten 11
struct Treap{
Treap* son[2];
Treap* fa;
int sze,val;
uint weight;
Treap(){val=-999999999,sze=0,weight=nextUint(),son[0]=son[1]=fa=this;}
inline void update(){
sze=son[0]->sze+son[1]->sze+1;
son[0]->fa=son[1]->fa=this;
}
}*null=new Treap(),*root=null,*stack[stan],*x,*last,*posi[stan];
typedef pair<Treap*,Treap*> D;
int n,m,s,u,a[stan];
char ord[sten];
inline Treap* newtreap(int val){
Treap* pos=new Treap();
pos->son[1]=pos->son[0]=pos->fa=null;
pos->sze=1;pos->val=val;pos->weight=nextUint();
return pos;
}
inline Treap* merge(Treap* a,Treap* b){
if(a==null) return b;
if(b==null) return a;
if(a->weight<b->weight){
a->son[1]=merge(a->son[1],b);
a->update();
return a;
}else{
b->son[0]=merge(a,b->son[0]);
b->update();
return b;
}
}
inline D split(Treap* pos,int k){
if(pos==null) return D(null,null);
D y;
if(pos->son[0]->sze>=k){
y=split(pos->son[0],k);
pos->son[0]=y.second;
pos->update();
y.second=pos;
}else{
y=split(pos->son[1],k-1-pos->son[0]->sze);
pos->son[1]=y.first;
pos->update();
y.first=pos;
}
return y;
}
inline Treap* build(){
int p=0;
for(int i=1;i<=n;++i){
a[i]=read();
posi[a[i]]=x=newtreap(a[i]);last=null;
while(p&&stack[p]->weight>x->weight){
stack[p]->update();
last=stack[p];
stack[p--]=null;
}
if(p) stack[p]->son[1]=x;x->fa=stack[p];
x->son[0]=last;last->fa=x;
stack[++p]=x;
}
while(p) stack[p--]->update();
return stack[1];
}
inline int getrank(Treap* pos){
int ret=pos->son[0]->sze;
while(pos->fa!=null&&pos->fa!=NULL){
if(pos==pos->fa->son[1]) ret+=pos->fa->son[0]->sze+1;
pos=pos->fa;
}
return ret;
}
inline void addhead(int x){
int k=getrank(posi[x]);
D X=split(root,k);
D y=split(X.second,1);
root=merge(y.first,merge(X.first,y.second));
return ;
}
inline void addtail(int x){
int k=getrank(posi[x]);
D X=split(root,k);
D y=split(X.second,1);
root=merge(X.first,merge(y.second,y.first));
return ;
}
void addmid(int xxx,int opt) {
if(!opt) return ;
static D X,y,z;
int k=getrank(posi[xxx]);
X=split(root, k);
y=split(X.second,1);
if(opt==-1)X=split(X.first,X.first->sze-1), root=merge(merge(X.first,y.first),merge(X.second,y.second));
else z=split(y.second,1), root=merge(merge(X.first,z.first),merge(y.first,z.second));
}
inline int getkth(int k){
D X=split(root,k-1);
D y=split(X.second,1);
Treap* pos=y.first;
root=merge(X.first,merge(pos,y.second));
return pos->val;
}
signed main(){
n=read();m=read();
root=build();
while(m--){
scanf("%s",ord);s=read();
switch(ord[0]){
case 'T':addhead(s);break;
case 'B':addtail(s);break;
case 'I':u=read();addmid(s,u);break;
case 'A':write(getrank(posi[s]));puts("");break;
case 'Q':write(getkth(s));puts("");break;
}
}
return 0;
}


(5)CQOI2014排序机械臂

题面还是有链接就是这里

很中规中矩的不固定排列序+区间修改

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<iomanip>
using namespace std;
inline int read(){
int i=0,f=1;
char ch;
for(ch=getchar();!isdigit(ch);ch=getchar())
if(ch=='-') f=-1;
for(;isdigit(ch);ch=getchar())
i=(i<<3)+(i<<1)+(ch^48);
return i*f;
}
int buf[1024];
inline void write(int x){
if(!x){putchar('0');return ;}
if(x<0){putchar('-');x=-x;}
while(x){buf[++buf[0]]=x%10,x/=10;}
while(buf[0]) putchar(buf[buf[0]--]+48);
return ;
}
typedef unsigned int uint;
inline uint nxtunit(){
static uint seed=19260817;
seed^=seed<<13;
seed^=seed>>17;
seed^=seed<<5;
return seed;
}
#define stan 111111
struct Treap{
Treap* son[2];
Treap* fa;
int sze,val;
uint weight;
bool flip;
Treap(){val=-999999999,sze=0,weight=nxtunit(),son[0]=son[1]=fa=this;flip=false;}
inline void update(){
sze=son[0]->sze+son[1]->sze+1;
son[0]->fa=son[1]->fa=this;
}
}*null=new Treap(),*root=null,*stack[stan],*x,*last,*posi[stan];
typedef pair<Treap*,Treap*> D;
int n,m,s,u,a[stan],to[stan];
struct thing{
int ord,val;
}thi[stan];
inline bool cmp(const thing &a,const thing &b){
if(a.val!=b.val) return a.val<b.val;
else return a.ord<b.ord;
}
inline Treap* newtreap(int val){
Treap* pos=new Treap();
pos->son[1]=pos->son[0]=pos->fa=null;
pos->sze=1;pos->val=val;pos->weight=nxtunit();
pos->flip=false;
return pos;
}
inline void pushdown(Treap* pos){
if(pos==null||pos==NULL) return ;
if(pos->flip){
pos->flip^=1;
pos->son[0]->flip^=1;
pos->son[1]->flip^=1;
swap(pos->son[0],pos->son[1]);
}
return ;
}
inline Treap* merge(Treap* a,Treap* b){
if(a==null) return b;
if(b==null) return a;
pushdown(a);pushdown(b);
if(a->weight<b->weight){
a->son[1]=merge(a->son[1],b);
a->update();
return a;
}else{
b->son[0]=merge(a,b->son[0]);
b->update();
return b;
}
}
inline D split(Treap* pos,int k){
if(pos==null) return D(null,null);
D y;pushdown(pos);
if(pos->son[0]->sze>=k){
y=split(pos->son[0],k);
pos->son[0]=y.second;
pos->update();
y.second=pos;
}else{
y=split(pos->son[1],k-1-pos->son[0]->sze);
pos->son[1]=y.first;
pos->update();
y.first=pos;
}
return y;
}
inline void rotate(Treap* pos){
if(pos==null||pos==NULL) return ;
rotate(pos->fa);
pushdown(pos);
return ;
}
inline int getrank(Treap* pos){
rotate(pos);
int ret=pos->son[0]->sze+1;
while(pos->fa!=null&&pos->fa!=NULL){
if(pos==pos->fa->son[1]) ret+=pos->fa->son[0]->sze+1;
pos=pos->fa;
}
return ret;
}
inline int getans(int d){
int ret=getrank(posi[d]);
D x=split(root,ret);
D y=split(x.first,d-1);
y.second->flip^=1;
root=merge(merge(y.first,y.second),x.second);
return ret;
}
signed main(){
n=read();
for(int i=1;i<=n;++i){
a[i]=read();thi[i].ord=i;thi[i].val=a[i];
}
sort(thi+1,thi+n+1,cmp);
for(int i=1;i<=n;++i)
to[thi[i].ord]=i;
for(int i=1;i<=n;++i){
posi[to[i]]=newtreap(a[i]);
root=merge(root,posi[to[i]]);
}
for(int i=1;i<n;++i){
write(getans(i));
putchar(' ');
}
write(getans(n));
return 0;
}


(6) NOI2005维修数列

题面在这里

如果你上面五道题都A了,这个题也不难想

写就是另一回事了

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<iomanip>
using namespace std;
inline int read(){
int i=0,f=1;
char ch;
for(ch=getchar();!isdigit(ch);ch=getchar())
if(ch=='-') f=-1;
for(;isdigit(ch);ch=getchar())
i=(i<<3)+(i<<1)+(ch^48);
return i*f;
}
int buf[1024];
inline void write(int x){
if(!x){putchar('0');return ;}
if(x<0){putchar('-');x=-x;}
while(x){buf[++buf[0]]=x%10,x/=10;}
while(buf[0]) putchar(buf[buf[0]--]+48);
return ;
}
#define stan 555555
struct Treap{
Treap* son[2];
int val,weight,sze,sum,l,r,m;bool flip,mark;
Treap(){val=l=r=m=-999999999,sum=sze=0;mark=flip=0;weight=rand();}
inline void update(){
sze=son[1]->sze+son[0]->sze+1;
sum=son[1]->sum+son[0]->sum+val;
l=max(son[0]->l,max(son[0]->sum+val,son[0]->sum+val+son[1]->l));
r=max(son[1]->r,max(son[1]->sum+val,son[1]->sum+val+son[0]->r));
m=max(son[0]->m,max(max(0,son[0]->r)+val+max(0,son[1]->l),son[1]->m));
}
}*null=new Treap(),*root=null,*stack[stan],*x,*last;
typedef pair<Treap*,Treap*> D;
int n,m,a[stan];
char ord[stan];
inline void maintain_flip(Treap* pos){
if(pos==null) return ;
pos->flip^=1;swap(pos->l,pos->r);
return ;
}
inline void maintain_mark(Treap* pos,int c){
if(pos==null) return ;
pos->val=c;pos->sum=pos->sze*c;
pos->l=pos->r=pos->m=max(pos->sze*c,c);
pos->mark=true;
return ;
}
inline void pushdown(Treap *pos){
if(pos==null) return ;
if(pos->flip){
pos->flip^=1;
maintain_flip(pos->son[0]);
maintain_flip(pos->son[1]);
swap(pos->son[0],pos->son[1]);
}
if(pos->mark){
maintain_mark(pos->son[0],pos->val);
maintain_mark(pos->son[1],pos->val);
pos->mark=0;
}
return ;
}
inline Treap* newtreap(int val)
{
Treap *pos=new Treap();
pos->son[1]=pos->son[0]=null;pos->weight=rand();
pos->val=pos->sum=val;pos->sze=1;pos->flip=pos->mark=0;
pos->m=pos->l=pos->r=val;
return pos;
}
Treap* merge(Treap* a,Treap* b){
if(a==null) return b;
if(b==null) return a;
pushdown(a);pushdown(b);
if(a->weight<b->weight){
a->son[1]=merge(a->son[1],b);
a->update();
return a;
}else{
b->son[0]=merge(a,b->son[0]);
b->update();
return b;
}
}
D split(Treap* pos,int k){
if(pos==null) return D(null,null);
D y;pushdown(pos);
if(pos->son[0]->sze>=k){
y=split(pos->son[0],k);
pos->son[0]=y.second;
pos->update();
y.second=pos;
}else{
y=split(pos->son[1],k-1-pos->son[0]->sze);
pos->son[1]=y.first;
pos->update();
y.first=pos;
}
return y;
}
inline Treap* build(){
int p=0;
for(int i=1;i<=n;++i){
a[i]=read();
x=newtreap(a[i]);last=null;
while(p&&stack[p]->weight>x->weight){
stack[p]->update();
last=stack[p];
stack[p--]=null;
}
if(p) stack[p]->son[1]=x;
x->son[0]=last;stack[++p]=x;
}
while(p) stack[p--]->update();
return stack[1];
}
inline void adjust(Treap *pos){
if(pos==null) return;
if(pos->son[0]!=null) adjust(pos->son[0]);
if(pos->son[1]!=null) adjust(pos->son[1]);
delete pos;return ;
}
inline void insert(){
int sta;sta=read();n=read();
Treap* pos=build();
D x=split(root,sta);
root=merge(x.first,merge(pos,x.second));
return ;
}
inline void remove(){
int sta;sta=read();n=read();
D x=split(root,sta-1);
D y=split(x.second,n);
adjust(y.first);
root=merge(x.first,y.second);
return ;
}
inline void reverse(){
int sta;sta=read();n=read();
D x=split(root,sta-1);
D y=split(x.second,n);
maintain_flip(y.first);
root=merge(x.first,merge(y.first,y.second));
return ;
}
inline void make_same(){
int sta,c;sta=read();n=read();c=read();
D x=split(root,sta-1);
D y=split(x.second,n);
maintain_mark(y.first,c);
root=merge(x.first,merge(y.first,y.second));
return ;
}
inline int get_sum(){
int sta;sta=read();n=read();
if(n==0) return 0;
D x=split(root,sta-1);
D y=split(x.second,n);
int ret=y.first->sum;
root=merge(x.first,merge(y.first,y.second));
return ret;
}
signed main(){
n=read();m=read();
root=build();
while(m--){
scanf("%s",ord);
switch(ord[0]){
case 'I':{insert();break;}
case 'D':{remove();break;}
case 'M':{
if(ord[2]=='K'){make_same();break;}
else {write(root->m);puts("");break;}
}
case 'G':{write(get_sum());puts("");break;}
case 'R':{reverse();break;}
}
}
return 0;
}


小结

终于是又水了一篇

其实我觉得LadyLex的讲解才是坠吼的传送门

%%%LadyLex

同时感谢Xehoth大佬在看到我在内网莫名血T之后甩给了我一个强大的随机数生成器

%%%Xehoth
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: