传送门1
传送门2
传送门3
写在前面:woc……woc……大家知道为什么这么久没写题解了吧
思路:不会用指针千万别用!千万别手贱多写函数!千万多调用splay!
感谢http://blog.csdn.net/leolin_/article/details/6436037
http://codevs.cn/wiki/solution/?problem_id=4543
solution16851
注意:数组版splay,个人不喜欢压行,代码写了4k,个人感觉思路还是蛮清晰的,没有特别的技巧,不推荐作为模板使用
代码:
#include"bits/stdc++.h"
using namespace std;
int n,root,tot;
struct os
{
int left,right,father,sz,occ,data;
}a[300000];
void ct(int root)
{
a[root].sz=a[root].occ+a[a[root].left].sz+a[a[root].right].sz;
}
void made(int x)
{
a[++tot].data=x;
a[tot].sz=a[tot].occ=1;
}
void rotate(int x,bool flag)
{
int y=a[x].father;
if (flag)
{
a[y].left=a[x].right;
if (a[x].right) a[a[x].right].father=y;
a[x].father=a[y].father;
if (a[y].father)
{
if (a[a[y].father].left==y)
a[a[y].father].left=x;
else a[a[y].father].right=x;
}
a[x].right=y;
a[y].father=x;
}
else
{
a[y].right=a[x].left;
if (a[x].left) a[a[x].left].father=y;
a[x].father=a[y].father;
if (a[y].father)
{
if (a[a[y].father].left==y)
a[a[y].father].left=x;
else a[a[y].father].right=x;
}
a[x].left=y;
a[y].father=x;
}
ct(y);
ct(x);
}
void splay(int x,int goal)
{
int y;
while (a[x].father!=goal)
{
y=a[x].father;
if (a[y].father==goal)
{
if (a[y].left==x) rotate(x,1);
else rotate(x,0);
}
else if (a[a[y].father].left==y)
{
if (a[y].left==x) rotate(y,1);
else rotate(x,0);
rotate(x,1);
}
else
{
if (a[y].right==x) rotate(y,0);
else rotate(x,1);
rotate(x,0);
}
}
if (!goal) root=x;
}
void insert(int now,int x)
{
if (!root) {made(x);root=tot;return;}
int flag=0;
while (!flag)
{
a[now].sz++;
if (a[now].data==x) a[now].occ++,flag=2;
else if (a[now].data>x)
{
if (!a[now].left) made(x),a[now].left=tot,a[tot].father=now,flag=1;
else now=a[now].left;
}
else
{
if (!a[now].right) made(x),a[now].right=tot,a[tot].father=now,flag=1;
else now=a[now].right;
}
}
splay((flag==1)?tot:now,0);
}
int find(int now,int x)
{
while (now)
{
if (a[now].data==x) {splay(now,0);return now;}
else if (a[now].data>x) now=a[now].left;
else now=a[now].right;
}
return 0;
}
int find_max(int now)
{
int pa=a[now].father;
if (!now) return 0;
while (a[now].right) now=a[now].right;
splay(now,pa);
return now;
}
int find_min(int now)
{
int pa=a[now].father;
if (!now) return 0;
while (a[now].left) now=a[now].left;
splay(now,pa);
return now;
}
int find_next_min(int x)
{
int ans=0,now=root;
while (now)
{
if (a[now].data>=x) now=a[now].left;
else ans=(a[now].data>a[ans].data||!ans)?now:ans,now=a[now].right;
}
splay(ans,0);
return ans;
}
int find_next_max(int x)
{
int ans=0,now=root;
while (now)
{
if (a[now].data<=x) now=a[now].right;
else ans=(a[now].data<a[ans].data||!ans)?now:ans,now=a[now].left;
}
splay(ans,0);
return ans;
}
bool del(int x)
{
int now=find(root,x);
if (!now) return 0;
splay(now,0);
if (a[now].occ>1)
{
--a[now].occ;
--a[now].sz;
return 1;
}
if (!a[now].left&&!a[now].right) root=0;
else if (!a[now].left)
{
root=a[now].right;
a[a[now].right].father=0;
}
else if (!a[now].right)
{
root=a[now].left;
a[a[now].left].father=0;
}
else
{
splay(find_max(a[now].left),root);
a[a[now].left].right=a[now].right;
a[a[now].right].father=a[now].left;
a[a[now].left].father=0;
root=a[now].left;
ct(a[now].left);
}
ct(now);
return 1;
}
int Kth(int k)
{
int now=root;
int p;
while (now)
{
p=a[a[now].left].sz;
if (k>p&&k<=p+a[now].occ) break;
if (k<=p) now=a[now].left;
else k-=(p+a[now].occ),now=a[now].right;
}
splay(now,0);
return now;
}
int find_rank(int x)
{
int ans=0,now=root;
while (1)
{
if (x<a[now].data) now=a[now].left;
else
{
if (x==a[now].data)
{
ans+=a[a[now].left].sz+1;
break;
}
else ans+=a[a[now].left].sz+a[now].occ,now=a[now].right;
}
}
splay(now,0);
return ans;
}
main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
if (x==1) insert(root,y);
else if (x==2) del(y);
else if (x==3) printf("%d\n",find_rank(y));
else if (x==4) printf("%d\n",a[Kth(y)].data);
else if (x==5) printf("%d\n",a[find_next_min(y)].data);
else if (x==6) printf("%d\n",a[find_next_max(y)].data);
}
}