就是贴个版,:-(,心累。
以下是旋转的:
#include <iostream> #include <cstdlib> #include <cstdio> const int N = 100000 + 11; using namespace std; struct treap { int l,r,key,size,rd,cnt; void news(int k) { size = cnt = 1;key = k; rd = rand(); } }tree[N]; int n,sum,root,ans; void updata(int k) { tree[k].size = tree[k].cnt + tree[tree[k].l].size + tree[tree[k].r].size; } void rturn(int &k) { int t = tree[k].l; tree[k].l = tree[t].r; tree[t].r = k; tree[t].size = tree[k].size; updata(k); k = t; } void lturn(int &k) { int t = tree[k].r; tree[k].r = tree[t].l; tree[t].l = k; tree[t].size = tree[k].size; updata(k); k = t; } void insert(int &k,int x) { if(k == 0){tree[++sum].news(x);k = sum; return;} ++tree[k].size; if(tree[k].key == x) ++tree[k].cnt; else if(x > tree[k].key) { insert(tree[k].r,x); if(tree[tree[k].r].rd < tree[k].rd)lturn(k); } else { insert(tree[k].l,x); if(tree[tree[k].l].rd < tree[k].rd) rturn(k); } } void del(int &k,int x) { if(k == 0) return; if(tree[k].key == x) { if(tree[k].cnt > 1) {--tree[k].cnt,--tree[k].size; return;} if(tree[k].l * tree[k].r == 0) k = tree[k].l + tree[k].r; else if(tree[tree[k].l].rd < tree[tree[k].r].rd) rturn(k), del(k,x); else lturn(k), del(k,x); } else if(x > tree[k].key) --tree[k].size, del(tree[k].r,x); else --tree[k].size, del(tree[k].l,x); } int query_rank(int k,int x) { if(k == 0) return 0; if(tree[k].key == x) return tree[tree[k].l].size + 1; else if(x > tree[k].key) return tree[tree[k].l].size + tree[k].cnt + query_rank(tree[k].r,x); else return query_rank(tree[k].l,x); } int query_num(int k,int x) { if(k == 0)return 0; if(x <= tree[tree[k].l].size) return query_num(tree[k].l,x); else if(x > tree[tree[k].l].size + tree[k].cnt) return query_num(tree[k].r,x-tree[tree[k].l].size - tree[k].cnt); else return tree[k].key; } void query_pro(int k,int x) { if(k == 0)return; if(tree[k].key < x) ans = k,query_pro(tree[k].r,x); else query_pro(tree[k].l,x); } void query_nxt(int k,int x) { if(k == 0)return; if(tree[k].key > x) ans = k,query_nxt(tree[k].l,x); else query_nxt(tree[k].r,x); } int main() { scanf("%d",&n); int op,x; for(int i = 1; i <= n; ++i) { scanf("%d%d",&op,&x); switch(op) { case 1: insert(root,x); break; case 2: del(root,x); break; case 3: printf("%d ",query_rank(root,x)); break; case 4: printf("%d ",query_num(root,x)); break; case 5: ans = 0; query_pro(root,x); printf("%d ",tree[ans].key); break; case 6: ans = 0; query_nxt(root,x); printf("%d ",tree[ans].key); break; } } return 0; }
以下是不用旋转的:
#include <algorithm> #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #define mp make_pair using namespace std; const int N = 100000 + 11,inf = 1 << 30; typedef pair <int,int> pir; int n,ans,size,root; struct Treap { int l,r,key,rnt,size; void news(int k) { size = 1,key = k,rnt = rand(); } }tree[N]; void updata(int x) { tree[x].size = tree[tree[x].l].size + tree[tree[x].r].size + 1; } pir split(int a,int n) { if(n == 0) return mp(0,a); int l = tree[a].l, r = tree[a].r; if(n == tree[l].size){tree[a].l = 0,updata(a); return mp(l,a);} if(n == tree[l].size + 1){tree[a].r = 0,updata(a); return mp(a,r);} if(n < tree[l].size) { pir tmp = split(l,n); tree[a].l = tmp.second,updata(a); return mp(tmp.first,a); } pir tmp = split(r,n - tree[l].size - 1); tree[a].r = tmp.first,updata(a); return mp(a,tmp.second); } int merge(int a,int b) { if(a == 0 || b == 0) return a + b; if(tree[a].rnt < tree[b].rnt) {tree[a].r = merge(tree[a].r,b),updata(a); return a; } else {tree[b].l = merge(a,tree[b].l),updata(b); return b;} } int query_rank(int k,int x) { int ret = 0, tmp = inf; while(k) { if(x == tree[k].key) tmp = min(tmp,ret + tree[tree[k].l].size + 1); // cout<<tree[k].key<<" "<<tree[tree[k].l].size<<" "<<x<<endl; if(x > tree[k].key) ret += tree[tree[k].l].size + 1,k = tree[k].r; else k = tree[k].l; } return tmp == inf?ret:tmp; } void insert(int x) { int k = query_rank(root,x); pir tmp = split(root,k); tree[++size].news(x); root = merge(tmp.first,size); root = merge(root,tmp.second); } void del(int x) { int k = query_rank(root,x); pir t1 = split(root,k); pir t2 = split(t1.first,k-1); // cout<<t2.first<<" "<<t2.second<<endl; root = merge(t2.first,t1.second); } int query_num(int k,int x) { if(k == 0)return 0; if(x <= tree[tree[k].l].size) return query_num(tree[k].l,x); else if(x == tree[tree[k].l].size + 1) return tree[k].key; return query_num(tree[k].r,x - tree[tree[k].l].size - 1); } void query_pro(int k,int x) { if(k == 0)return; if(tree[k].key < x) ans = k,query_pro(tree[k].r,x); else query_pro(tree[k].l,x); } void query_nxt(int k,int x) { if(k == 0)return; if(tree[k].key > x) { ans = k, query_nxt(tree[k].l,x); } else query_nxt(tree[k].r,x); } int main() { freopen("treap.in","r",stdin); scanf("%d",&n); int op,x; while(n--) { scanf("%d%d",&op,&x); switch(op) { case 1: insert(x); break; case 2: del(x); break; case 3: printf("%d ",query_rank(root,x)); break; case 4: printf("%d ",query_num(root,x)); break; case 5: ans = 0; query_pro(root,x); printf("%d ",tree[ans].key); break; case 6: ans = 0; query_nxt(root,x); printf("%d ",tree[ans].key); break; } } return 0; }
(还是觉得splay写得好玩)