排名,修改,前驱和后继通过平衡树都很好实现,查询排名为k的值不是很好实现,因为这个区间可能在线段树的多个区间内,就需要在多棵平衡树中找,合并也不太现实,换个思路:二分值,找到排名小于k的最大值,然后在对它求一个后继就好了。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
using namespace std;
typedef long long ll;
const int inf=2147483647;
const int N=50010;
int n,m,a[N];
struct Treap
{
#define ls tr[rt].l
#define rs tr[rt].r
struct node
{
int l,r,sz,val,key;
}tr[N<<5];
int cnt=0;
int newnode(int val)
{
tr[++cnt].val=val;
tr[cnt].key=rand();
tr[cnt].sz=1;
return cnt;
}
void pushup(int rt){
tr[rt].sz=tr[ls].sz+tr[rs].sz+1; }
void split(int rt,int val,int &x,int &y)
{
if(!rt)
{
x=y=0;
return ;
}
if(tr[rt].val<=val)
{
x=rt;
split(tr[rt].r,val,tr[x].r,y);
pushup(x);
return ;
}
y=rt;
split(tr[rt].l,val,x,tr[rt].l);
pushup(y);
}
int merge(int x,int y)
{
if(!x||!y) return x+y;
if(tr[x].key<=tr[y].key)
{
tr[x].r