题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3224
blibli学习视频链接:https://www.bilibili.com/video/av46204315/?p=2 感谢大佬,虽然我还是不知道Split和Merge的原理(滑稽)
我知道它们一个可以拆树,一个可以合树。知道一些性质,然后就莫得咯。(也许这就是所谓的不求甚解吧,emmm(自我安慰,实在看不懂原理),略懂就行了,不重要了!)。
无旋streap模板:
#include<algorithm>
#include<string.h>
#include<stdio.h>
#define ls(x) A[x].child[0]
#define rs(x) A[x].child[1]
using namespace std;
struct node
{
int child[2],Size,v,key;
} A[100010];
int tot;
inline int rand()
{
static int seed=233;
return seed = int(seed * 482711ll % 2147483647);
}
inline void up(int r)
{
A[r].Size=A[ls(r)].Size+A[rs(r)].Size+1;
return ;
}
void Split(int r,int& x,int& y,int k)
{
if(!r)
{
x=y=0;
return ;
}
if(A[r].v<=k) x=r,Split(rs(r),rs(x),y,k);
else y=r,Split(ls(r),x,ls(y),k);
up(r);
return ;
}
void Merge(int &r,int x,int y)
{
if(!x||!y)
{
r=x+y;
return ;
}
if(A[x].key<A[y].key) r=x,Merge(rs(r),rs(x),y);
else r=y,Merge(ls(r),x,ls(y));
up(r);
return ;
}
int Insert(int& r,int k)
{
int x=0,y=0,z=++tot;
A[z].v=k,A[z].Size=1,A[z].key=rand(),ls(z)=0,rs(z)=0;
Split(r,x,y,k);
Merge(x,x,z);
Merge(r,x,y);
return 0;
}
int del(int &r,int k)
{
int x=0,y=0,z=0;
Split(r,x,y,k);
Split(x,x,z,k-1);
Merge(z,ls(z),rs(z));
Merge(x,x,z);
Merge(r,x,y);
return 0;
}
int Rank(int &r,int k)
{
int x=0,y=0,ans;
Split(r,x,y,k-1);
ans=A[x].Size+1;
Merge(r,x,y);
return ans;
}
int kth(int r,int k)
{
if(A[r].Size+1<k) return -1;//不存在
while(A[ls(r)].Size+1!=k)
{
if(A[ls(r)].Size>=k) r=ls(r);
else k-=(A[ls(r)].Size+1),r=rs(r);
}
return A[r].v;
}
int pre(int &r,int k)
{
int x=0,y=0,ans;
Split(r,x,y,k-1);
ans=kth(x,A[x].Size);
Merge(r,x,y);
return ans;
}
int sub(int &r,int k)
{
int x=0,y=0,ans;
Split(r,x,y,k);
ans=kth(y,1);
Merge(r,x,y);
return ans;
}
int main()
{
int root=0,t,opt,x;
tot=0;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&opt,&x);
if(opt==1) Insert(root,x);
if(opt==2) del(root,x);
if(opt==3) printf("%d\n",Rank(root,x));
if(opt==4) printf("%d\n",kth(root,x));
if(opt==5) printf("%d\n",pre(root,x));
if(opt==6) printf("%d\n",sub(root,x));
}
return 0;
}