又是一道SPLAY!!!
庆祝!!!
其实这是一道splay模板题,然而我却和傻子一样开心!
毕竟我是机房中最菜的,他们都会splay,就我不会。
网上都是数组版本,难道只有我是指针吗???(凯爷你出来!)
这个题不是简单以权值来建立平衡树,而是以下标
这个我觉得挺难理解的。
这样的话插入其实就是找到下标为 i 的节点然后插入在它的前面就好了
#include<bits/stdc++.h>
#define lca long long
using namespace std;
const lca inf = 999999999LL ;
const int MX = 80005 ;
int n,m,tem,t;
char op[105];
int rd()
{
int x=0;
char c=getchar();
while(!isdigit(c))
c=getchar();
while(isdigit(c))
x=10*x+c-'0',c=getchar();
return x;
}
struct splay_node{
int siz,w;
splay_node * son[2] , * fa ;
splay_node(int _w,splay_node *_fa)
{
siz=1;
fa=_fa;
w=_w;
son[0]=son[1]=0;
}
bool dir() { return this==fa->son[1]; }
}*rt=0,*pos[MX];
void maintain(splay_node * o)
{
o->siz=1;
for(int i=0;i<2;i++)
if(o->son[i])
o->siz+=o->son[i]->siz,o->son[i]->fa=o;
}
void rorate(splay_node * o)
{
splay_node * p =o->fa;
int d=o->dir();
p->son[d]=o->son[d^1];
o->son[d^1]=p;
o->fa=p->fa;
if(p->fa) p->fa->son[p->dir()]=o;
maintain(p),maintain(o);
}
void splay(splay_node * o ,splay_node * t)
{
while(o->fa!=t)
{
splay_node * p = o->fa;
if(p->fa==t) rorate(o);
else if(p->dir()==o->dir()) rorate(p),rorate(o);
else rorate(o),rorate(o);
}
if(!t) rt=o;
}
splay_node * find(splay_node * o,int k)
{
if(!o->son[0]&&k==1) return o;
if(!o->son[0]) return find(o->son[1],k-1);
if(o->son[0]->siz==k-1) return o;
if(o->son[0]->siz>=k) return find(o->son[0],k);
else return find(o->son[1],k-1-o->son[0]->siz);
}
void insert(int k,int w)
{
splay_node * o = find(rt,k);
splay(o,0);
splay_node * p = find(o->son[1],1);
splay(p,o);
splay_node * temp = new splay_node (w,p);
p->son[0]=temp;
p->siz++;
o->siz++;
pos[w]=temp;
}
void del(splay_node * o)
{
splay(o,0);
if(!o->son[0]&&o->son[1]) o->son[1]->fa=0,rt=o->son[1];
else if(!o->son[1]&&o->son[0]) o->son[0]->fa=0,rt=o->son[0];
else if(!o->son[0]&&!o->son[1]) rt=0;
else
{
o->son[0]->fa=o->son[1]->fa=0;
splay_node * p = o->son[0];
while(p->son[1])
p=p->son[1];
splay(p,0);
p->son[1]=o->son[1];
maintain(p);
}
}
int ask(splay_node * o)
{
splay(o,0);
return o->son[0]->siz;
}
int main()
{
n=rd(),m=rd();
rt=new splay_node(-inf,0);
rt->son[1]=new splay_node(inf,rt);
rt->siz++;
for(int i=1;i<=n;i++)
{
scanf("%d",&tem);
insert(i,tem);
}
for(int i=1;i<=m;i++)
{
scanf("%s%d",op,&tem);
if(op[0]=='Q')
{
tem++;
printf("%d\n",find(rt,tem)->w);
}
else if(op[0]=='A')
{
printf("%d\n",ask(pos[tem])-1);
}
else if(op[0]=='T')
{
del(pos[tem]);
insert(1,tem);
}
else if(op[0]=='B')
{
del(pos[tem]);
insert(n,tem);
}
else
{
scanf("%d",&t);
int num=ask(pos[tem]);
del(pos[tem]);
insert(num+t,tem);
}
}
}
心得:
1.不一定要以权值建平衡树
2.要加入虚节点防止边界问题
3.删点啊查询啊要考虑儿子是否为空