模板:替罪羊树
一种平衡树,暴力重构,发现不平衡就重新建树
感谢小红指出我的错误,改完之后发现。。。时间变成了原来的两倍。。。
人丑自带大常数
那么粘一个小红的代码吧,我的时间实在是不太乐观
#include<cstdio> #include<iostream> #include<cstring> #include<vector> using namespace std; const double al=0.7; struct node { node *l,*r; int val,size,cnt; bool del; bool bad() { return l->cnt>al*cnt+5||r->cnt>al*cnt+5; } void up() { size=!del+l->size+r->size; cnt=1+l->cnt+r->cnt; } }; node *null,**badtag; void dfs(node *k,vector<node*> &v) { if(k==null)return ; dfs(k->l,v); if(!k->del)v.push_back(k); dfs(k->r,v); if(k->del)delete k; } node *build(vector<node*> &v,int l,int r) { if(l>=r)return null; int mid=l+r>>1; node *k=v[mid]; k->l=build(v,l,mid); k->r=build(v,mid+1,r); k->up(); return k; } void rebuild(node* &k) { vector<node*> v; dfs(k,v); k=build(v,0,v.size()); } void insert(int x,node* &k) { if(k==null) { k=new node; k->l=k->r=null; k->del=0; k->size=k->cnt=1; k->val=x; return ; } else { ++k->size;++k->cnt; if(x>=k->val)insert(x,k->r); else insert(x,k->l); if(k->bad())badtag=&k; else if(badtag!=&null) k->cnt-=(*badtag)->cnt-(*badtag)->size; } } void ins(int x,node* &k) { badtag=&null; insert(x,k); if(badtag!=&null)rebuild(*badtag); } int getrk(node *now,int x) { int ans=1; while(now!=null) { if(now->val>=x)now=now->l; else { ans+=now->l->size+!now->del; now=now->r; } } return ans; } int kth(node *now,int x) { while(now!=null) { if(!now->del&&now->l->size+1==x) return now->val; if(now->l->size>=x)now=now->l; else { x-=now->l->size+!now->del; now=now->r; } } } void erase(node *k,int rk) { if(!k->del&&rk==k->l->size+1) { k->del=1; --k->size; return ; } --k->size; if(rk<=k->l->size+!k->del)erase(k->l,rk); else erase(k->r,rk-k->l->size-!k->del); } node *root;int n; int main() { null=new node; root=null; scanf("%d",&n); while(n--) { int op,x; scanf("%d%d",&op,&x); switch(op) { case 1:ins(x,root);break; case 2:erase(root,getrk(root,x));break; case 3:printf("%d\n",getrk(root,x));break; case 4:printf("%d\n",kth(root,x));break; case 5:printf("%d\n",kth(root,getrk(root,x)-1));break; case 6:printf("%d\n",kth(root,getrk(root,x+1)));break; } } return 0; }
算了还是粘一个自己的700ms代码:
#include <vector> #include <iostream> #include <cstdio> using namespace std; const double alpha = 0.75; int n, opt, x; struct node { node *ls, *rs; int val, size, cnt; bool deleted; bool isbad() { return ls->cnt > alpha * cnt + 5 || rs->cnt > alpha * cnt + 5; } void maintain() { size = !deleted + ls->size + rs->size; cnt = 1 + ls->cnt + rs->cnt; } } * null, *root, **badtag; struct ScapeGoat_Tree { private: void dfs(node *k, vector<node *> &v) { if (k == null) return; dfs(k->ls, v); if (!k->deleted) v.push_back(k); dfs(k->rs, v); if (k->deleted) delete k; } node *build(vector<node *> &v, int l, int r) { if (l >= r) return null; int mid = (l + r) >> 1; node *k = v[mid]; k->ls = build(v, l, mid); k->rs = build(v, mid + 1, r); k->maintain(); return k; } void rebuild(node *&k) { vector<node *> v; dfs(k, v); k = build(v, 0, v.size()); } public: void insert(int x, node *&k) { badtag = &null; if (k == null) { k = new node; k->ls = k->rs = null; k->deleted = false; k->size = k->cnt = 1; k->val = x; return; } else { ++k->size; ++k->cnt; if (x >= k->val) insert(x, k->rs); else insert(x, k->ls); if (k->isbad()) badtag = &k; else if (badtag == &null) k->cnt -= (*badtag)->cnt - (*badtag)->size; } if (badtag != &null) rebuild(*badtag); } int get_rank(node *k, int x) { int ans = 1; while (k != null) { if (k->val >= x) k = k->ls; else { ans += k->ls->size + !k->deleted; k = k->rs; } } return ans; } int get_kth(node *k, int x) { while (k != null) { if (!k->deleted && k->ls->size + 1 == x) return k->val; if (k->ls->size >= x) k = k->ls; else { x -= k->ls->size + !k->deleted; k = k->rs; } } } void erase(node *k, int rk) { if (!k->deleted && rk == k->ls->size + 1) { k->deleted = 1; --k->size; return; } --k->size; if (rk <= k->ls->size + !k->deleted) erase(k->ls, rk); else erase(k->rs, rk - k->ls->size - !k->deleted); } } SGT; int main() { null = new node; root = null; scanf("%d", &n); while (n--) { scanf("%d%d", &opt, &x); if (opt == 1) SGT.insert(x, root); else if (opt == 2) SGT.erase(root, SGT.get_rank(root, x)); else if (opt == 3) printf("%d\n", SGT.get_rank(root, x)); else if (opt == 4) printf("%d\n", SGT.get_kth(root, x)); else if (opt == 5) printf("%d\n", SGT.get_kth(root, SGT.get_rank(root, x) - 1)); else if (opt == 6) printf("%d\n", SGT.get_kth(root, SGT.get_rank(root, x + 1))); } }
以普通平衡树为例:
#include<vector> #include<iostream> #include<cstdio> using namespace std; const double alpha=0.75; int n,opt,x; struct node{ node *ls,*rs; int val,size,cnt; bool deleted; bool isbad(){ return ls->cnt>alpha*cnt+5||rs->cnt>alpha*cnt+5; } void maintain(){ size=!deleted+ls->size+rs->size; cnt=1+ls->cnt+rs->cnt; } }*null,*root; struct ScapeGoat_Tree{ private: void dfs(node *k,vector<node*> &v){ if(k==null) return; dfs(k->ls,v); if(!k->deleted) v.push_back(k); dfs(k->rs,v); if(k->deleted) delete k; } node *build(vector<node*> &v,int l,int r){ if(l>=r) return null; int mid=(l+r)>>1; node *k=v[mid]; k->ls=build(v,l,mid); k->rs=build(v,mid+1,r); k->maintain(); return k; } void rebuild(node* &k){ vector<node*>v; dfs(k,v); k=build(v,0,v.size()); } public: void insert(int x,node* &k){ if(k==null){ k=new node; k->ls=k->rs=null; k->deleted=false; k->size=k->cnt=1; k->val=x; return; }else{ ++k->size; ++k->cnt; if(x>=k->val) insert(x,k->rs); else insert(x,k->ls); if(k->isbad())rebuild(k); } } int get_rank(node *k,int x){ int ans=1; while(k!=null){ if(k->val>=x) k=k->ls; else{ ans+=k->ls->size+!k->deleted; k=k->rs; } } return ans; } int get_kth(node *k,int x){ while(k!=null){ if(!k->deleted && k->ls->size+1==x) return k->val; if(k->ls->size>=x) k=k->ls; else{ x-=k->ls->size+!k->deleted; k=k->rs; } } } void erase(node *k,int rk){ if(!k->deleted && rk==k->ls->size+1){ k->deleted=1; --k->size; return; } --k->size; if(rk<=k->ls->size+!k->deleted) erase(k->ls,rk); else erase(k->rs,rk-k->ls->size-!k->deleted); } }SGT; int x1,y1; int main(){ null=new node; root=null; scanf("%d",&n); while(n--){ scanf("%d%d",&opt,&x); if(opt==1) SGT.insert(x,root); else if(opt==2) SGT.erase(root,SGT.get_rank(root,x)); else if(opt==3) printf("%d\n",SGT.get_rank(root,x)); else if(opt==4) printf("%d\n",SGT.get_kth(root,x)); else if(opt==5) printf("%d\n",SGT.get_kth(root,SGT.get_rank(root,x)-1)); else if(opt==6) printf("%d\n",SGT.get_kth(root,SGT.get_rank(root,x+1))); } }