(内容更新ing)
Treap
首先是标准的Treap,楼上的dalao们已经说的很清楚了
// treap my 数组
#include <algorithm>
#include <iostream>
#include <cstdio>
#define FOR(i,n,m) for(int i=n;i<=m;++i)
#define il inline
using namespace std;
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
static char buf[100000],*pa(buf),*pb(buf);
#define gc pa==pb&&(pb=(pa=buf)+fread(buf,1,100000,stdin),pa==pb)?EOF:*pa++ //玄学快读
il int read()
{
register int x(0);register int f(1);register char c(gc);
while((c<'0'||c>'9')&&c!='-')c=gc;
c=='-'?f=-1,c=gc:f;
while(c>='0'&&c<='9')x=x*10+(c^48),c=gc;
return f*x;
}
const int N=100100,INF=(1<<29);
struct Treap {
int lc,rc,key,pri,size,cnt;
}a[N];
#define c(x) a[x].cnt
#define s(x) a[x].size
#define p(x) a[x].pri
#define v(x) a[x].key
#define rc(x) a[x].rc
#define lc(x) a[x].lc
#define up(k) s(k)=s(rc(k))+s(lc(k))+c(k);
//懒人的宏定义方便书写
int tot,rt;
il void zig(int &k) { //左旋
int y=lc(k);
lc(k)=rc(y);
rc(y)=k;
s(y)=s(k);
up(k)
k=y;
}
il void zag(int &k) { //右旋
int y=rc(k);
rc(k)=lc(y);
lc(y)=k;
s(y)=s(k);
up(k)
k=y;
}
il void insert(int &k,const int &key) { // 插入
if(!k) {
k=++tot;
v(k)=key;
p(k)=rand();
c(k)=s(k)=1;
lc(k)=rc(k)=0;
return;
}
else ++s(k);
if(v(k)==key) ++c(k);
else if(key<v(k)) {
insert(lc(k),key); //向左搜
if(p(lc(k))<p(k)) zig(k); //左儿子优先级小,左旋
}
else {
insert(rc(k),key);
if(p(rc(k))<p(k)) zag(k);
}
return;
}
il void del(int &k,const int &key) { //删除元素
if(v(k)==key) {
if(c(k)>1) --c(k),--s(k);
else if(!lc(k) || !rc(k)) k=lc(k)+rc(k);
else if(p(lc(k))<p(rc(k))) zig(k),del(k,key);
else zag(k),del(k,key);
return;
}
--s(k);
if(key<v(k)) del(lc(k),key);
else del(rc(k),key);
return;
}
il int querypre(int key) { //前驱
int x=rt,res=-INF;
while(x) {
if(v(x)<key) res=v(x),x=rc(x);
else x=lc(x);
}
return res;
}
il int querysuf(int key) { //后继
int x=rt,res=INF;
while(x) {
if(v(x)>key) res=v(x),x=lc(x);
else x=rc(x);
}
return res;
}
il int querykth(int k) { //查找第k大元素
int x=rt;
while(x) {
if(s(lc(x))<k&&s(lc(x))+c(x)>=k) return v(x);
if(s(lc(x))>=k) x=lc(x);
else k-=s(lc(x))+c(x),x=rc(x);
}
return 0;
}
il int querdrank(int key) { //查找元素排名
int x=rt,res=0;
while(x) {
if(key==v(x)) return res+s(lc(x))+1;
if(key<v(x)) x=lc(x);
else res+=s(lc(x))+c(x),x=rc(x);
}
return res;
}
void print(int x)
{
if(!x) return;
print(lc(x));
cout<<x<<" "<<s(x)<<endl;
print(rc(x));
}
void work() {
int n=read();
FOR(i,1,n) {
int a=read(),x=read();
if(a==1) insert(rt,x);
if(a==2) del(rt,x);
if(a==3) cout<<querdrank(x)<<endl;
if(a==4) cout<<querykth(x)<<endl;
if(a==5) cout<<querypre(x)<<endl;
if(a==6) cout<<querysuf(x)<<endl;
}
return;
}
int main() {
work();
return 0;
}
整个的代码实现难度不大,主要要注意前驱,后继之类的等号问题。。(因为这个wa了很久)
表示题解里面指针写的特别少。。。然后作为一个刚开始学指针的表示很无奈。。
下一段代码送给指针党
//Treap my 指针
#include <algorithm>
#include <iostream>
#include <cstdio>
#define FOR(i,n,m) for(int i=n;i<=m;++i)
#define FR(i,n,m) for(int i=n;i>=m;--i)
#define re register
#define gc getchar()
using namespace std;
const int N=100010,INF=(1<<29);
inline int read() {
re int x(0),f(1);
re char ch=gc;
while(ch<'0'||ch>'9') {
if(ch=='-') f=-1;
ch=gc;
}
while(ch>='0'&&ch<='9') {
x=(x<<1)+(x<<3)+(ch^48);
ch=gc;
}
return x*f;
}
struct node {
node* ch[2]; //写成这个样子之后旋转就不用写两个了
int pri,val,size,cnt;
node() {
ch[0]=ch[1]=NULL;
pri=rand();
val=size=cnt=1;
}
void update() {
size=(ch[0]==NULL?0:ch[0]->size)+(ch[1]==NULL?0:ch[1]->size)+cnt;
}
};
node* root;
struct treap {
inline void rotate (node* &k,int d) { //1右,0左
node* y=k->ch[d^1];
k->ch[d^1]=y->ch[d];
y->ch[d]=k;
y->size=k->size;
k->update();
k=y;
}
inline void insert(node* &k,const int &key) {
if(k==NULL) {
k=new node;
k->val=key;
return;
}
++k->size;
if(k->val==key) {++k->cnt;return;}
int a=key>k->val;
insert(k->ch[a],key);
if(k->ch[a]->pri>k->pri) rotate(k,a^1);
}
inline void del(node* &k,const int &key) {
if(k==NULL) return;
if(k->val==key) {
if(k->cnt>1) --k->cnt,--k->size;
else if(k->ch[0]==NULL&&k->ch[1]==NULL) k=NULL;
else if(k->ch[0]==NULL) k=k->ch[1];
else if(k->ch[1]==NULL) k=k->ch[0];
else rotate(k,(int)(k->ch[0]->pri>k->ch[1]->pri)),del(k,key);
return;
}
--k->size;
del(k->ch[key>k->val],key);
}
inline int queryrank(const int &key) {
node* k=root;
int ans(0);
while(k!=NULL) {
if(k->val==key) return ans+(k->ch[0]?k->ch[0]->size:0)+1;
if(k->val>key) k=k->ch[0];
else ans+=(k->ch[0]?k->ch[0]->size:0)+k->cnt,k=k->ch[1];
}
return ans;
}
inline int querykth(int rank) {
node* k=root;
while(k!=NULL) {
int res=k->ch[0]?k->ch[0]->size:0;
if(res<rank&&res+k->cnt>=rank) return k->val;
if(res>=rank) k=k->ch[0];
else rank-=res+k->cnt,k=k->ch[1];
}
return 0;
}
inline int querypre(const int &key) {
node* k=root;
int ans=-INF;
while(k) {
if(k->val>=key) k=k->ch[0];
else ans=k->val,k=k->ch[1];
}
return ans==-INF?-1:ans;
}
inline int querysuf(const int &key) {
node* k=root;
int ans=INF;
while(k) {
if(k->val<=key) k=k->ch[1];
else ans=k->val,k=k->ch[0];
}
return ans==INF?-1:ans;
}
}Treap;
void work() {
int n=read();
while(n--) {
int op=read(),x=read();
int ans;
switch(op) {
case 1:Treap.insert(root,x);break;
case 2:Treap.del(root,x);break;
case 3:cout<<Treap.queryrank(x)<<endl;break;
case 4:cout<<Treap.querykth(x)<<endl;break;
case 5:cout<<Treap.querypre(x)<<endl;break;
case 6:cout<<Treap.querysuf(x)<<endl;break;
}
}
}
int main() {
// freopen("y.txt","r",stdin);
// freopen(".out","w",stdout);
work();
return 0;
}
树状数组
其实这道题目还可以用树状数组水过去。。。然后树状数组常数小,所以跑的非常非常非常地快(一百多是跑的比较快地了吧)
最重要的是 码量非常小
//树状数组
#include<cstdio>
#include <iostream>
using namespace std;
const int M=10000001;
int f[20000002],n,vmax=20000001;
#define lowbit(x) (x&(-x))
inline void add(int x,int k){
while(x<=vmax) {
f[x]+=k;
x+=lowbit(x);
}
}
inline int getRank(int x){
int sum(0);x;
while(x) {
sum+=f[x];
x-=lowbit(x);
}
return sum;
}
int find(int k){
int ans=0,cnt=0;
for(int i=25;i>=0;i--){
ans+=(1<<i);
if(ans>vmax||cnt+f[ans]>=k)
ans-=(1<<i);
else
cnt+=f[ans];
}
return ++ans;
}
int tp;
int main(){
// freopen("y.txt","r",stdin);
// freopen("o.txt","w",stdout);
n=read();
int opt,x;
while(n--){
opt=read(),x=read();
x+=M;
switch(opt) {
case 1:add(x,1);break;
case 2:add(x,-1);break;
case 3:write(getRank(x-1)+1);break;
case 4:x-=M;write(find(x)-M);break;
case 5:write(find(getRank(x-1))-M);break;
case 6:write(find(getRank(x)+1)-M);break;
}}
}
(我爱树状数组)
SBT树
像SBT树这种跑的快的树是很棒的
先皮一个指针:
扫描二维码关注公众号,回复:
5463514 查看本文章
#include <cstdio>
#include <iostream>
using namespace std;
inline int min(int a,int b){return a<b?a:b;}
inline int max(int a,int b){return b<a?a:b;}
const int INF=(1<<29),N=100010;
int tot;
struct node {
int val,size;
node* ch[2];
node() {
ch[0]=ch[1]=NULL;
size=1;
}
void pushup() {
size=(ch[0]?ch[0]->size:0)+(ch[1]?ch[1]->size:0)+1;
}
};
node* root=NULL;
inline void rotate (node* &k,int d) {
node* y=k->ch[d^1];
k->ch[d^1]=y->ch[d];
y->ch[d]=k;
y->size=k->size;
k->pushup();
k=y;
}
inline void maintain(node* &x,int way) {
if(way) {
if(x->ch[1]==NULL) return;
node* y=x->ch[1];
if((y->ch[1]?y->ch[1]->size:0)>(x->ch[0]?x->ch[0]->size:0))
rotate(x,0);
else if((y->ch[0]?y->ch[0]->size:0)>(x->ch[0]?x->ch[0]->size:0))
rotate(x->ch[1],1),rotate(x,0);
else return;
}
else {
if(x->ch[0]==NULL) return;
node* y=x->ch[0];
if((y->ch[0]?y->ch[0]->size:0)>(x->ch[1]?x->ch[1]->size:0))
rotate(x,1);
else if((y->ch[1]?y->ch[1]->size:0)>(x->ch[1]?x->ch[1]->size:0))
rotate(x->ch[0],0),rotate(x,1);
else return;
}
if(x->ch[0]!=NULL) maintain(x->ch[0],0);
if(x->ch[1]!=NULL) maintain(x->ch[1],1);
if(x!=NULL) maintain(x,1),maintain(x,0);
}
inline void insert(node* &now,int val) {
if(now==NULL) {
now=new node;
now->val=val;
return;
}
++now->size;
insert(now->ch[val>now->val],val);
maintain(now,now->val<=val);
}
inline void del(node* &now,int val) {
if(now==NULL) return;
--now->size;
if(now->val==val) {
if(now->ch[0]==NULL&&now->ch[1]==NULL) now=NULL;
else if(now->ch[0]==NULL) now=now->ch[1];
else if(now->ch[1]==NULL) now=now->ch[0];
else {
node* y=now->ch[1];
while(y->ch[0]!=NULL) y=y->ch[0];
now->val=y->val;
del(now->ch[1],y->val);
}
}
else del(now->ch[now->val<val],val);
}
inline int rank(node* now,int val) {
if(now==NULL) return 1;
if(now->val<val) return rank(now->ch[1],val)+(now->ch[0]?now->ch[0]->size:0)+1;
return rank(now->ch[0],val);
}
inline int kth(node* now,int k) {
if(now==NULL) return 0;
int res=(now->ch[0]?now->ch[0]->size:0);
if(res+1==k) return now->val;
if(res<k) return kth(now->ch[1],k-(now->ch[0]?now->ch[0]->size:0)-1);
return kth(now->ch[0],k);
}
inline int querypre(node* now,int val) {
if(now==NULL)
return ~INF+1;
if(now->val>=val)
return querypre(now->ch[0],val);
return max(now->val,querypre(now->ch[1],val));
}
inline int querysuf(node* now,int val) {
if(now==NULL) return INF;
if(now->val<=val) return querysuf(now->ch[1],val);
return min(now->val,querysuf(now->ch[0],val));
}
int main() {
// freopen("y.txt","r",stdin);
// freopen("1.out","w",stdout);
int n,opt,x;
scanf("%d",&n);
while(n--) {
scanf("%d%d",&opt,&x);
switch(opt) {
case 1:
insert(root,x);break;
case 2:
del(root,x);break;
case 3:
printf("%d\n",rank(root,x));break;
case 4:
printf("%d\n",kth(root,x));break;
case 5:
printf("%d\n",querypre(root,x));break;
case 6:
printf("%d\n",querysuf(root,x));
}
}
return 0;
}
下面是大家都看的比较爽的数组:
#include<cstdio>
#define INF 987654321
#define N 100010
inline int min(int a,int b){return a<b?a:b;}
inline int max(int a,int b){return a>b?a:b;}
int root,tot,lc[N],rc[N],val[N],siz[N];
inline void update(int now){siz[now]=siz[lc[now]]+siz[rc[now]]+1;}
inline void lr(int& x){int y=rc[x];rc[x]=lc[y],lc[y]=x,siz[y]=siz[x],update(x),x=y;}
inline void rr(int& x){int y=lc[x];lc[x]=rc[y],rc[y]=x,siz[y]=siz[x],update(x),x=y;}
inline void maintain(int& now,int way)
{
if(way)
{
if(siz[rc[rc[now]]]>siz[lc[now]])lr(now);
else if(siz[lc[rc[now]]]>siz[lc[now]])rr(rc[now]),lr(now);
else return;
}
else
{
if(siz[lc[lc[now]]]>siz[rc[now]])rr(now);
else if(siz[rc[lc[now]]]>siz[rc[now]])lr(lc[now]),rr(now);
else return;
}
maintain(lc[now],0);
maintain(rc[now],1);
maintain(now,1);
maintain(now,0);
}
inline void insert(int& now,int v)
{
if(!now){now=++tot,val[now]=v,siz[now]=1;return;}
++siz[now];
if(val[now]>v)insert(lc[now],v);
else insert(rc[now],v);
maintain(now,val[now]<=v);
}
inline void del(int& now,int v)
{
if(!now)return;
--siz[now];
if(val[now]==v)
{
if(!lc[now]||!rc[now])now=lc[now]+rc[now];
else
{
int tp=rc[now];
while(lc[tp])tp=lc[tp];
val[now]=val[tp];
del(rc[now],val[tp]);
}
}
else if(val[now]>v)del(lc[now],v);
else del(rc[now],v);
}
inline int rank(int now,int v)
{
if(!now)return 1;
else if(val[now]<v)return rank(rc[now],v)+siz[lc[now]]+1;
else return rank(lc[now],v);
}
inline int kth(int now,int v)
{
if(!now)return -1;
if(siz[lc[now]]+1==v)return val[now];
else if(v<=siz[lc[now]])return kth(lc[now],v);
else return kth(rc[now],v-siz[lc[now]]-1);
}
inline int pred(int now,int v)
{
if(!now)return -INF;
if(val[now]<v)return max(val[now],pred(rc[now],v));
else return pred(lc[now],v);
}
inline int succ(int now,int v)
{
if(!now)return INF;
if(val[now]>v)return min(val[now],succ(lc[now],v));
else return succ(rc[now],v);
}
int n,opt,x;
int main()
{
n=read();
while(n--)
{
opt=read(),x=read();
switch(opt)
{
case 1:insert(root,x);break;
case 2:del(root,x);break;
case 3:write(rank(root,x));break;
case 4:write(kth(root,x));break;
case 5:write(pred(root,x));break;
case 6:write(succ(root,x));
}
}
return 0;
}
fhq_treap
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<ctime>
using namespace std;
const int N=100010;
struct trnode {
int son[2],v,rnd,size;
}tr[N];
int tot=0,root=0;
void update(int x) {
tr[x].size=tr[tr[x].son[0]].size+tr[tr[x].son[1]].size+1;
}
int new_code(int v) {
tot++;
tr[tot].size=1;
tr[tot].v=v;
tr[tot].rnd=rand();
return tot;
}
int merge(int x,int y) {
if(!x || !y) return x+y;
if(tr[x].rnd<tr[y].rnd) {
tr[x].son[1]=merge(tr[x].son[1],y);
update(x);
return x;
}
else {
tr[y].son[0]=merge(x,tr[y].son[0]);
update(y);
return y;
}
}
void split(int now,int k,int &x,int &y) {
if(!now) x=y=0;
else {
if(tr[now].v<=k)
x=now,split(tr[now].son[1],k,tr[now].son[1],y);
else
y=now,split(tr[now].son[0],k,x,tr[now].son[0]);
update(now);
}
}
int kth(int now,int k) {
while(1) {
if(k<=tr[tr[now].son[0]].size)
now=tr[now].son[0];
else {
if(k==tr[tr[now].son[0]].size+1) return now;
else {
k-=tr[tr[now].son[0]].size+1;
now=tr[now].son[1];
}
}
}
}
int main() {
// freopen("3.in","r",stdin);
srand((unsigned)time(NULL));
int T;
int flag,x,y,z,a,b;
scanf("%d",&T);
while(T--) {
scanf("%d%d",&flag,&a);
if(flag==1) {
split(root,a,x,y);
root=merge(merge(x,new_code(a)),y);
}
else if(flag==2) {
split(root,a,x,z);
split(x,a-1,x,y);
y=merge(tr[y].son[0],tr[y].son[1]);
root=merge(merge(x,y),z);
}
else if(flag==3) {
split(root,a-1,x,y);
printf("%d\n",tr[x].size+1);
root=merge(x,y);
}
else if(flag==4)
printf("%d\n",tr[kth(root,a)].v);
else if(flag==5) {
split(root,a-1,x,y);
printf("%d\n",tr[kth(x,tr[x].size)].v);
root=merge(x,y);
}
else if(flag==6) {
split(root,a,x,y);
printf("%d\n",tr[kth(y,1)].v);
root=merge(x,y);
}
}
return 0;
}
Splay
(不要管为什么我闲的发疯打指针)
#include <algorithm>
#include <iostream>
#include <cstdio>
#define FOR(i,n,m) for(int i=n;i<=m;++i)
#define FR(i,n,m) for(int i=n;i>=m;--i)
#define re register
#define gc getchar()
using namespace std;
const int N=100010,INF=(1<<29);
inline int read() {
re int x(0),f(1);
re char ch=gc;
while(ch<'0'||ch>'9') {
if(ch=='-') f=-1;
ch=gc;
}
while(ch>='0'&&ch<='9') {
x=(x<<1)+(x<<3)+(ch^48);
ch=gc;
}
return x*f;
}
struct node {
int val,size,cnt;
node* fa,*ch[2];
node(const int &x,node* father):val(x),size(1),cnt(1),fa(father)
{ch[0]=ch[1]=NULL;}
inline void pushup() {
size=(ch[0]?ch[0]->size:0)+(ch[1]?ch[1]->size:0)+cnt;
}
inline int find() {
return fa->ch[1]==this;
}
inline int path(const int &new_date) {return new_date>=val;}
} * root;
inline void rotate(node* x) {
node* y(x->fa);
node* z(y->fa);
int k(x->find());
y->ch[k]=x->ch[k^1];
if(x->ch[k^1]!=NULL) x->ch[k^1]->fa=y;
z==NULL?root=x:z->ch[y->find()]=x;
x->ch[k^1]=y;
y->fa=x;
x->fa=z;
y->pushup(),x->pushup();
}
inline void Splay(node* x,node* goal) {
while(x->fa!=goal) {
node* y(x->fa);
node* z(y->fa);
if(z==goal) rotate(x);
else {
if(x->find()^(y->find())) rotate(x),rotate(x);
else rotate(y),rotate(x);
}
}
}
inline void insert(const int &val) {
if(root==NULL) {
root=new node(val,NULL);
return;
}
for(node* t=root;t!=NULL;t=t->ch[t->path(val)]) {
if(t->val==val) {++t->cnt,Splay(t,NULL);return;}
if(t->ch[t->path(val)]==NULL) {
t->ch[t->path(val)]=new node(val,t);
Splay(t->ch[t->path(val)],NULL);
return;
}
}
}
inline void del(const int &val) {
node* t(root);
while(t!=NULL) {
if(t->val==val) break;
t=t->ch[t->path(val)];
}
if(t==NULL) return;
Splay(t,NULL);
if(t->cnt>1) {--t->cnt;return;}
if(t==NULL) return;
if(t->ch[0]==NULL) {
root=t->ch[1];
if(root!=NULL) root->fa=NULL;
}
else {
node* p(t->ch[0]);
while(p->ch[1]!=NULL) p=p->ch[1];
Splay(p,t),root=p;
root->fa=NULL;
p->ch[1]=t->ch[1];
if(p->ch[1]!=NULL) p->ch[1]->fa=p;
}
}
inline void find(const int &val) {
node* t(root);
while(t!=NULL&&t->val!=val) t=t->ch[t->path(val)];
if(t!=NULL) Splay(t,NULL);
}
inline int kth(int k) {
node* t(root);
while(t!=NULL) {
int res(t->ch[0]?t->ch[0]->size:0);
if(res<k&&res+t->cnt>=k) return t->val;
else if(k<=res) t=t->ch[0];
else k-=res+t->cnt,t=t->ch[1];
}
}
inline int lower(const int &val) {
node* t(root);
int res;
while(t!=NULL) {
if(t->val<val) res=t->val,t=t->ch[1];
else t=t->ch[0];
}
return res;
}
inline int upper(const int &val) {
node* t(root);
int res;
while(t!=NULL) {
if(t->val>val) res=t->val,t=t->ch[0];
else t=t->ch[1];
}
return res;
}
int main() {
// freopen("y.in","r",stdin);
int T=read();
while(T--) {
switch(read()) {
case(1):insert(read());break;
case(2):del(read());break;
case(3):find(read()),printf("%d\n",(root->ch[0]?root->ch[0]->size:0)+1);break;
case(4):printf("%d\n",kth(read()));break;
case(5):printf("%d\n",lower(read()));break;
case(6):printf("%d\n",upper(read()));break;
}
}
return 0;
}
(持续更新ing)