目前见过作为名次树实现的用法,其他暂时没见过←_←
#include<bits/stdc++.h>
#include<stdio.h>
#include<algorithm>
#include<queue>
#include<string.h>
#include<iostream>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<iomanip>
using namespace std;
#define ll long long
#define ull unsigned long long
#define pb push_back
#define FOR(a) for(int i=1;i<=a;i++)
const int inf=0x3f3f3f3f;
const int maxn=2e6+7;
const long long mod=1e9+7;
struct NODE{
NODE *ch[2];
int v,r,s,w;//数据,名次,节点大小,数据出现次数
NODE(int v):v(v){
ch[0]=ch[1]=NULL;
r=rand();s=w=1;
}
bool operator < (const NODE &rhs)const{return r<rhs.r;}
int cmp(int x)const{
if(x==v)return -1;
return x<v?0:1; //左边0右边1
}
int cmp1(int x)const{ //第k大查询的比较
int sz=w;
if(ch[0])sz+=ch[0]->s;
if(sz-w+1<=x && x<=sz)return -1;//找到自身
if(x<=sz-w)return 0;
return 1;
}
void maintain(){
s=w;if(ch[0])s+=ch[0]->s;if(ch[1])s+=ch[1]->s;
}
}*root;
void rotate(NODE* &o,int d){ //0左旋
NODE *k=o->ch[d^1];
o->ch[d^1]=k->ch[d];
k->ch[d]=o;
o->maintain();k->maintain();
o=k;
}
void insert(NODE* &o,int v){
if(!o){ //空节点
o=new NODE(v);
return;
}else{
int d=o->cmp(v);
if(d==-1)o->w++;
else{
insert(o->ch[d],v); //先插到叶子,再往上旋
if(o->ch[d]>o)rotate(o,d^1);//左儿子大就右旋~
}
}
o->maintain();
}
void del(NODE* &o,int v){
int d=o->cmp(v);
if(d==-1){
if(o->w > 1)o->w--;
else if(o->ch[0]&&o->ch[1]){
int d2=0;
if(o->ch[0]>o->ch[1])d2=1;
rotate(o,d2);
del(o->ch[d2],v);
}else{
if(o->ch[0])o=o->ch[0];
else o=o->ch[1];
}
}else del(o->ch[d],v);
if(o)o->maintain();
}
void remove(NODE* &o){
if(!o)return;
if(o->ch[0])remove(o->ch[0]);
if(o->ch[1])remove(o->ch[1]);
delete o;
o=NULL;
}
int find(NODE* &o,int x){
if(o==NULL)return 0;
int d=o->cmp(x);
if(d==-1)return o->w;
return find(o->ch[d],x);
}
int kth(NODE* o,int k){ //按尺寸进子树查找
int d=o->cmp1(k);
int sz=o->w;
if(o->ch[0])sz+=o->ch[0]->s;
if(d==-1)return o->v;
if(d==0)return kth(o->ch[0],k);
return kth(o->ch[1],k-sz);
}
int query(NODE *o,int x){ //求排名,前面有多少个
if(!o)return 0;
int d=o->cmp(x);
int sz=o->w;
if(o->ch[0])sz+=o->ch[0]->s;
if(d==-1)return sz-o->w;
else if(d==0)return query(o->ch[0],x);
else return query(o->ch[1],x)+sz;
}
/*
//求前驱:
int sz=query(root,x);
printf("%d
",kth(root,sz));
//求后继:
int sz=query(root,x);
sz+=find(root,x)+1;
printf("%d
",kth(root,sz));
int main(){
insert(root,1);
insert(root,2);
insert(root,3);
cout<<query(root,3)<<endl;
}
*/
int main(){
int n;scanf("%d",&n);
int op,x;
while(n--){
scanf("%d%d",&op,&x);
if(op==1){insert(root,x);}
else if(op==2){
del(root,x);
}else if(op==3){
printf("%d
",query(root,x)+1);
}else if(op==4){
printf("%d
",kth(root,x));
}else if(op==5){
int sz=query(root,x);
printf("%d
",kth(root,sz));
}else if(op==6){
int sz=query(root,x);
sz+=find(root,x)+1;
printf("%d
",kth(root,sz));
}
}
}
哪天有空细化一下分类吧。。
--------------------------------------------------------------
#include<bits/stdc++.h>
#include<stdio.h>
#include<algorithm>
#include<queue>
#include<string.h>
#include<iostream>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<iomanip>
using namespace std;
#define ll long long
#define ull unsigned long long
#define pb push_back
#define FOR(a) for(int i=1;i<=a;i++)
const int inf=0x3f3f3f3f;
const int maxn=2e6+7;
const long long mod=1e9+7;
inline int Random(){
static int seed=703;
return seed=int(seed*48271ll%2147483647);
}
struct NODE{
NODE *ch[2];
int v,r,s,w;//数据,名次,节点大小,数据出现次数
NODE(int v):v(v){
ch[0]=ch[1]=NULL;
r=Random();s=w=1;
}
bool operator < (const NODE &rhs)const{return r<rhs.r;}
inline int cmp(int x)const{
if(x==v)return -1;
return x<v?0:1; //左边0右边1
}
inline int cmp1(int x)const{ //第k大查询的比较
int sz=w;
if(ch[0])sz+=ch[0]->s;
if(sz-w+1<=x && x<=sz)return -1;//找到自身
if(x<=sz-w)return 0;
return 1;
}
inline void maintain(){
s=w;if(ch[0])s+=ch[0]->s;if(ch[1])s+=ch[1]->s;
}
}*root;
inline void rotate(NODE* &o,int d){ //0左旋
NODE *k=o->ch[d^1];
o->ch[d^1]=k->ch[d];
k->ch[d]=o;
o->maintain();k->maintain();
o=k;
}
inline void insert(NODE* &o,int v){
if(!o){ //空节点
o=new NODE(v);
return;
}else{
int d=o->cmp(v);
if(d==-1)o->w++;
else{
insert(o->ch[d],v); //先插到叶子,再往上旋
if(o->ch[d]>o)rotate(o,d^1);//左儿子大就右旋~
}
}
o->maintain();
}
inline void del(NODE* &o,int v){
int d=o->cmp(v);
if(d==-1){
if(o->w > 1)o->w--;
else if(o->ch[0]&&o->ch[1]){
int d2=0;
if(o->ch[0]>o->ch[1])d2=1;
rotate(o,d2);
del(o->ch[d2],v);
}else{
if(o->ch[0])o=o->ch[0];
else o=o->ch[1];
}
}else del(o->ch[d],v);
if(o)o->maintain();
}
inline void remove(NODE* &o){
if(!o)return;
if(o->ch[0])remove(o->ch[0]);
if(o->ch[1])remove(o->ch[1]);
delete o;
o=NULL;
}
inline int find(NODE* &o,int x){
if(o==NULL)return 0;
int d=o->cmp(x);
if(d==-1)return o->w;
return find(o->ch[d],x);
}
inline int kth(NODE* o,int k){ //按尺寸进子树查找
int d=o->cmp1(k);
int sz=o->w;
if(o->ch[0])sz+=o->ch[0]->s;
if(d==-1)return o->v;
if(d==0)return kth(o->ch[0],k);
return kth(o->ch[1],k-sz);
}
inline int query(NODE *o,int x){ //求排名,前面有多少个
if(!o)return 0;
int d=o->cmp(x);
int sz=o->w;
if(o->ch[0])sz+=o->ch[0]->s;
if(d==-1)return sz-o->w;
else if(d==0)return query(o->ch[0],x);
else return query(o->ch[1],x)+sz;
}
/*
//求前驱:
int sz=query(root,x);
printf("%d
",kth(root,sz));
//求后继:
int sz=query(root,x);
sz+=find(root,x)+1;
printf("%d
",kth(root,sz));
int main(){
insert(root,1);
insert(root,2);
insert(root,3);
cout<<query(root,3)<<endl;
}
*/
int main(){
int n;scanf("%d",&n);
int op,x;
while(n--){
scanf("%d%d",&op,&x);
if(op==1){insert(root,x);}
else if(op==2){
del(root,x);
}else if(op==3){
printf("%d
",query(root,x)+1);
}else if(op==4){
printf("%d
",kth(root,x));
}else if(op==5){
int sz=query(root,x);
printf("%d
",kth(root,sz));
}else if(op==6){
int sz=query(root,x);
sz+=find(root,x)+1;
printf("%d
",kth(root,sz));
}
}
}
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
数组版,写起来舒服多了,但多次删除会存在爆空间的可能
#include<bits/stdc++.h>
#include<stdio.h>
#include<algorithm>
#include<queue>
#include<string.h>
#include<iostream>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<iomanip>
using namespace std;
#define ll long long
#define ull unsigned long long
#define pb push_back
#define FOR(a) for(int i=1;i<=a;i++)
const int inf=0x3f3f3f3f;
const int maxn=1e5+7;
const long long mod=1e9+7;
int nodecnt,root;
int val[maxn],happen[maxn],l[maxn],r[maxn],rnd[maxn],size[maxn];
void maintain(int x){size[x]=size[l[x]]+size[r[x]]+happen[x];}
void rturn(int &k){int t=l[k];l[k]=r[t];r[t]=k;maintain(k);maintain(t);k=t;}
void lturn(int &k){int t=r[k];r[k]=l[t];l[t]=k;maintain(k);maintain(t);k=t;}
void insert1(int &x,int v){ //按大小
if(!x){
x=++nodecnt;
l[x]=r[x]=0;
val[x]=v;happen[x]=size[x]=1;rnd[x]=rand();return;
}
size[x]++;
if(val[x]==v)happen[x]++;
else if(v<val[x]){
insert1(l[x],v);
if(rnd[l[x]]<rnd[x])rturn(x);
}else{
insert1(r[x],v);
if(rnd[r[x]]<rnd[x])lturn(x);
}
}
void insert2(int &x,int v,int pos){ //按位置,0号位最前
if(!x){
x=++nodecnt;
val[x]=v;
rnd[x]=rand();size[x]=happen[x]=1;l[x]=r[x]=0;
return;
}
size[x]++;
if(size[l[x]]<pos){
insert2(r[x],v,pos-size[l[x]]-1);
if(rnd[r[x]]<rnd[x])lturn(x);
}else{
insert2(l[x],v,pos);
if(rnd[l[x]]<rnd[x])rturn(x);
}
}
void del(int &x,int v){
if(!x)return;
if(val[x]==v){
if(happen[x]>1){happen[x]--;size[x]--;return;}
if(!l[x]||!r[x])x=l[x]+r[x];
else if(rnd[l[x]]<rnd[r[x]]){rturn(x);del(x,v);}
else{lturn(x);del(x,v);}
}else{
size[x]--;
if(v<val[x])del(l[x],v);
else del(r[x],v);
}
}
int rnk(int x,int v){
if(!x)return 0;
if(val[x]==v)return size[l[x]]+1;
else if(v<val[x])return rnk(l[x],v);
else return size[l[x]]+happen[x]+rnk(r[x],v);
}
int kth(int x,int k){
if(!x)return 0;
if(k<=size[l[x]])return kth(l[x],k);
else if(k>size[l[x]]+happen[x])
return kth(r[x],k-size[l[x]]-happen[x]);
else return val[x];
}
int ans;
void pre(int x,int v){
if(!x)return;
if(v>val[x])ans=x,pre(r[x],v);
else pre(l[x],v);
}
void suf(int x,int v){
if(!x)return;
if(v<val[x])ans=x,suf(l[x],v);
else suf(r[x],v);
}
int main(){
int n;scanf("%d",&n);
int op,num;
FOR(n){
scanf("%d%d",&op,&num);
if(op==1){
insert1(root,num);
}else if(op==2){
del(root,num);
}else if(op==3){
printf("%d
",rnk(root,num));
}else if(op==4){
printf("%d
",kth(root,num));
}else if(op==5){
ans=0;
pre(root,num);
printf("%d
",val[ans]);
}else{
ans=0;
suf(root,num);
printf("%d
",val[ans]);
}
}
}