洛谷上的一道splay水题
但是不知为何做了很长时间
甚至还动用了洛谷的样例,可以说是非常菜了
跟正常的splay模版一样
但是有点细节需要注意
求前驱和后缀的方式十分巧妙,但是必须要求的是如果一个元素没有了,就必须让他的节点消失,
而不是把个数改成0就可以了,否则找到的当前这个点如果没有个数的话,可能是不如左子树的元素的
还有注意不仅insert后要splay到根,query过后也要到跟,防止深度过长导致时间复杂度骤升
嗯,就是这样
顺带一提这次noip差点退役,最后好死赖活着想继续省选
现在估计是省选的人里面最菜的一个了,唉。。。。。。
继续努力吧
#include<bits/stdc++.h>
using namespace std;
const int base=1e7+7;
struct node
{
node *son[2],*father;
int size,num,cnt;
}pool[3200005],*tail=pool,*root,*zero;
int n,shu1,shu2,all;
void update(node *nd)
{
nd->size=nd->son[0]->size+nd->son[1]->size+nd->cnt;
}
void rotate(node *nd)
{
node *p=nd->father;
node *pp=p->father;
int r1=p->son[0]==nd;
int r2=pp->son[1]==p;
node *s=nd->son[r1];
if(pp==zero) root=nd;
else pp->son[r2]=nd;
nd->father=pp;
p->father=nd;
nd->son[r1]=p;
if(s!=zero) s->father=p;
p->son[!r1]=s;
update(p);
update(nd);
}
void splay(node *nd,node *top)
{
while(nd->father!=top)
{
node *p=nd->father;
if(p->father==top)
{
rotate(nd);
}
else
{
node *pp=p->father;
if((pp->son[1]==p)==(p->son[1]==nd))
{
rotate(p);
rotate(nd);
}
else
{
rotate(nd);
rotate(nd);
}
}
}
}
void init()
{
zero=tail++;
zero->son[0]=zero->son[1]=zero->father=zero;
root=tail++;
root->son[0]=tail++;
root->son[1]=zero;
root->son[0]->son[0]=zero;
root->son[0]->son[1]=zero;
root->size=2;
root->cnt=1;
root->num=1e7+5;
root->son[0]->size=1;
root->son[0]->cnt=1;
root->son[0]->num=-1e7-5;
root->son[0]->father=root;
root->father=zero;
}
node *find_pos(int x)
{
node *pos=root;
while(233)
{
if(x<pos->num) pos=pos->son[0];
else if(x>pos->num) pos=pos->son[1];
else return pos;
}
}
node *find_num(int x)
{
x++;
node *pos=root;
while(233)
{
if(x<=pos->son[0]->size) pos=pos->son[0];
else if(x>pos->son[0]->size+pos->cnt) x-=pos->son[0]->size+pos->cnt,pos=pos->son[1];
else return pos;
}
}
void print(node *nd)
{
if(nd==zero) return;
print(nd->son[0]);
for(int i=1;i<=nd->cnt;i++)
printf("%d ",nd->num);
print(nd->son[1]);
}
void insert(node *&nd,node *fa,int num)
{
if(nd==zero)
{
nd=tail++;
nd->father=fa;
nd->son[0]=nd->son[1]=zero;
nd->size=1;
nd->cnt=1;
nd->num=num;
splay(nd,zero);
return;
}
if(num<nd->num) insert(nd->son[0],nd,num);
else if(num>nd->num) insert(nd->son[1],nd,num);
else {nd->cnt++;nd->size++;return;}
update(nd);
}
int query_pos(int x)
{
node *pos=root;
int ans=0;
while(233)
{
if(x<pos->num) pos=pos->son[0];
else if(x>pos->num) ans+=pos->size-pos->son[1]->size,pos=pos->son[1];
else
{
ans+=pos->son[0]->size;
splay(pos,zero);
return ans;
}
}
}
int query_num(int x)
{
node *one=find_num(x);
splay(one,zero);
return one->num;
}
void dilit(int x)
{
node *one=find_pos(x);
if(one->cnt==1)
{
int two=query_pos(x);
node *r1=find_num(two-1);
node *r2=find_num(two+1);
splay(r1,zero);
splay(r2,r1);
r2->son[0]=zero;
one=zero;
update(r2);
update(r1);
}
else
{
splay(one,zero);
one->cnt--;
one->size--;
}
}
int pre(int x)
{
int ans=-0x7fffffff;
node *pos=root;
while(233)
{
if(pos->num<x&&pos->num>ans&&pos->cnt) ans=pos->num;
if(x>pos->num) pos=pos->son[1];
else pos=pos->son[0];
if(pos==zero)
{
if(pos->father!=zero)
splay(pos->father,zero);
break;
}
}
return ans;
}
int suf(int x)
{
int ans=0x7fffffff;
node *pos=root;
while(233)
{
if(pos->num>x&&pos->num<ans&&pos->cnt) ans=pos->num;
if(x<pos->num) pos=pos->son[0];
else pos=pos->son[1];
if(pos==zero)
{
if(pos->father!=zero)
splay(pos->father,zero);
break;
}
}
return ans;
}
int main()
{
init();
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&shu1,&shu2);
if(shu1==1)
{
insert(root,zero,shu2);
all++;
}
else if(shu1==2)
{
dilit(shu2);
all--;
}
else if(shu1==3)
{
printf("%d\n",query_pos(shu2));
}
else if(shu1==4)
{
printf("%d\n",query_num(shu2));
}
else if(shu1==5)
{
printf("%d\n",pre(shu2));
}
else if(shu1==6)
{
printf("%d\n",suf(shu2));
}
}
return 0;
}
/*
4
1 2
2 2
1 2
3 2
*/