维护一个序列,要求支持区间加、区间翻转、区间最值.
复习Splay…
手感极差,写+调了1h,感觉药丸…
AC code:
#include <cstdio>
#include <algorithm>
using namespace std;
const int N=100010;
const int INF=1<<29;
int n,m,tot;
struct nod{
int v,mx,siz,tad;
bool rev;
nod *pr,*ch[2];
}*NIL,pool[N];
struct Splay{
nod *root;
Splay(){
NIL=root=&pool[tot++];
NIL->v=NIL->mx=-INF;
for(int i=0;i<=n+1;i++) insert(&root,NIL,0);
}
nod* newnod(nod *pre,int v){
nod *p=&pool[tot++];
p->v=p->mx=v;p->siz=1;
p->pr=pre;p->ch[0]=p->ch[1]=NIL;
return p;
}
void update(nod *p){
if(p==NIL) return ;
p->siz=p->ch[0]->siz+p->ch[1]->siz+1;
p->mx=max(p->v,max(p->ch[0]->mx,p->ch[1]->mx));
}
void clear(nod *p){
if(p==NIL||p==NULL) return ;
if(p->tad){
p->v+=p->tad;p->mx+=p->tad;
p->ch[0]->tad+=p->tad;p->ch[1]->tad+=p->tad;
p->tad=0;
}
if(p->rev){
nod *t=p->ch[0];p->ch[0]=p->ch[1];p->ch[1]=t;
p->ch[0]->rev^=1;p->ch[1]->rev^=1;p->rev=0;
}
}
void rotate(nod *x,bool t){
nod *y=x->pr,*z=y->pr,*b=x->ch[t^1];
b->pr=y;y->pr=x;x->pr=z;y->ch[t]=b;x->ch[t^1]=y;
if(z->ch[0]==y) z->ch[0]=x;
if(z->ch[1]==y) z->ch[1]=x;
clear(y->ch[0]);clear(y->ch[1]);clear(x->ch[t]);update(y);update(x);
}
void splay(nod *x,nod *obj){
while(x->pr!=obj){
nod *y=x->pr,*z=y->pr;
if(z==obj&&y->ch[0]==x) rotate(x,0);
else if(z==obj&&y->ch[1]==x) rotate(x,1);
else if(z->ch[0]==y&&y->ch[0]==x){rotate(y,0);rotate(x,0);}
else if(z->ch[1]==y&&y->ch[1]==x){rotate(y,1);rotate(x,1);}
else if(z->ch[1]==y){rotate(x,0);rotate(x,1);}
else{rotate(x,1);rotate(x,0);}
}
if(obj==NIL) root=x;
}
void insert(nod **p,nod *pre,int v){
if(*p==NIL){
*p=newnod(pre,v);
splay(*p,NIL);
return ;
}
(*p)->siz++;
insert(&(*p)->ch[0],*p,v);
}
nod* getkth(int k){
clear(root);
nod *p=root;
int rk=p->ch[0]->siz+1;
while(rk!=k){
if(rk>k){
p=p->ch[0];
clear(p);
rk-=p->ch[1]->siz+1;
}
else{
p=p->ch[1];
clear(p);
rk+=p->ch[0]->siz+1;
}
}
return p;
}
void add(int L,int R,int v){
splay(getkth(L),NIL);
splay(getkth(R+2),root);
root->ch[1]->ch[0]->tad+=v;
clear(root->ch[1]->ch[0]);clear(root->ch[1]->ch[1]);clear(root->ch[0]);
update(root->ch[1]);update(root);
}
void rvs(int L,int R){
splay(getkth(L),NIL);
splay(getkth(R+2),root);
root->ch[1]->ch[0]->rev^=1;
}
void getmax(int L,int R){
splay(getkth(L),NIL);
splay(getkth(R+2),root);
clear(root->ch[1]->ch[0]);
printf("%d\n",root->ch[1]->ch[0]->mx);
}
};
int main(){
scanf("%d%d",&n,&m);
Splay T;
for(int i=1;i<=m;i++){
int k,L,R,v;
scanf("%d",&k);
if(k==1){
scanf("%d%d%d",&L,&R,&v);
T.add(L,R,v);
}
else if(k==2){
scanf("%d%d",&L,&R);
T.rvs(L,R);
}
else{
scanf("%d%d",&L,&R);
T.getmax(L,R);
}
}
return 0;
}

本文介绍了一种基于Splay树的数据结构实现,能够高效地完成区间加、区间翻转和查询区间最大值等操作。文章通过具体代码展示了Splay树的节点结构、旋转、翻转等关键操作,并提供了完整的实现细节。

157

被折叠的 条评论
为什么被折叠?



