bzoj3224: Tyvj 1728 普通平衡树
treap模板。把ask_before和ask_after改成递归的形式会快很多。想把其他的操作也改成递归的形式。。。但是太麻烦了T_T
#include<cstdio> #include<cstring> #include<cctype> #include<algorithm> #include<cstdlib> #include<ctime> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) int read(){ int x=0,f=1;char c=getchar(); while(!isdigit(c)){ if(c=='-') f=-1;c=getchar(); } while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x*f; } const int nmax=1e5+5; struct node{ int l,r,v,sz,rd,w; };node ns[nmax]; int n,rt,cnt=0; void update(int x){ ns[x].sz=ns[ns[x].l].sz+ns[ns[x].r].sz+ns[x].w; } void rturn(int &x){ int t=ns[x].l;ns[x].l=ns[t].r;ns[t].r=x; ns[t].sz=ns[x].sz;update(x);x=t; } void lturn(int &x){ int t=ns[x].r;ns[x].r=ns[t].l;ns[t].l=x; ns[t].sz=ns[x].sz;update(x);x=t; } void insert(int &k,int x){ if(!k){ cnt++;k=cnt; ns[k].sz=ns[k].w=1;ns[k].v=x;ns[k].rd=rand(); return ; } ns[k].sz++; if(ns[k].v==x) ns[k].w++; else if(ns[k].v<x) { insert(ns[k].r,x); if(ns[ns[k].r].rd<ns[k].rd) lturn(k); }else{ insert(ns[k].l,x); if(ns[ns[k].l].rd<ns[k].rd) rturn(k); } } void del(int &k,int x){ if(!k) return ; if(ns[k].v==x){ if(ns[k].w>1) ns[k].w--,ns[k].sz--; else{ if(ns[k].l*ns[k].r==0) k=ns[k].l+ns[k].r; else if(ns[ns[k].l].rd<ns[ns[k].r].rd) rturn(k),del(k,x); else lturn(k),del(k,x); } }else if(x>ns[k].v) ns[k].sz--,del(ns[k].r,x); else ns[k].sz--,del(ns[k].l,x); } int ask_rank(int k,int x){ if(!k) return 0; if(ns[k].v==x) return ns[ns[k].l].sz+1; else if(x>ns[k].v) return ns[ns[k].l].sz+ns[k].w+ask_rank(ns[k].r,x); else return ask_rank(ns[k].l,x); } int ask_num(int k,int x){ if(!k) return 0; if(x<=ns[ns[k].l].sz) return ask_num(ns[k].l,x); else if(x>ns[ns[k].l].sz+ns[k].w) return ask_num(ns[k].r,x-ns[ns[k].l].sz-ns[k].w); else return ns[k].v; } int ask_before(int x){ int t=rt,ans=0; while(t){ if(ns[t].v<x) ans=ns[t].v,t=ns[t].r; else t=ns[t].l; } return ans; } int ask_after(int x){ int t=rt,ans=0; while(t){ if(ns[t].v>x) ans=ns[t].v,t=ns[t].l; else t=ns[t].r; } return ans; } int main(){ srand(10000007); n=read();int u,v,d; rep(i,1,n){ u=read(),v=read(); if(u==1) insert(rt,v); else if(u==2) del(rt,v); else if(u==3) printf("%d\n",ask_rank(rt,v)); else if(u==4) printf("%d\n",ask_num(rt,v)); else if(u==5) printf("%d\n",ask_before(v)); else printf("%d\n",ask_after(v)); } return 0; } /* 10 1 106465 4 1 1 317721 1 460929 1 644985 1 84185 1 89851 6 81968 1 492737 5 493598 */
3224: Tyvj 1728 普通平衡树
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 8619 Solved: 3651
[Submit][Status][Discuss]
Description
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)
Input
第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)
Output
对于操作3,4,5,6每行输出一个数,表示对应答案
Sample Input
10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
Sample Output
106465
84185
492737
84185
492737
HINT
1.n的数据范围:n<=100000
2.每个数的数据范围:[-1e7,1e7]
数据如下http://pan.baidu.com/s/1jHMJwO2