替罪羊树&&非旋treap

题解:

替罪羊树的模板和splay差距还是比较大的。。

按照我的splay的写法 真是都是问题。。

替罪羊树就是暴力的搞

当某颗子树大小大于这棵树的alpha时 就退出

另外删除的时候打懒标记删除

当有用个数少于alpha*n的时候,就重构

注意点:

1.找rank的时候要找比它小的个数,不能像splay那样取min

2.删除的时候要删排名为这个的,不能删这个数

以上两点的原因是

不能保证相同元素一定在左子树内,因为重构可能造成在右子树

另外找pre和scc也就不能和splay一样了

rank(x) 找的是编号最小的那个

rank(x)-1就是前驱

rank(x+1) 就是后继

替罪羊树不支持区间操作

应该写它的用处就是用来搞毒瘤树套树的。。

#include <bits/stdc++.h>
using namespace std;
#define rint register int
#define IL inline
#define rep(i,h,t) for (rint i=h;i<=t;i++)
#define dep(i,t,h) for (rint i=t;i>=h;i--)
#define mid ((h+t)>>1)
const double alpha=0.75;
const int INF=2e9+10; 
const int N=4e6+10;
int s[N],n,m,top,rt,t1;
struct phs{
  int ls[N],rs[N],siz[N],travel[N],cnt[N],v[N];
  bool f[N];
  void dfs(int x)
  {
    if (!x) return;
    dfs(ls[x]);
    if (f[x]) travel[++t1]=x;
    else s[++top]=x; 
    dfs(rs[x]);
  }
  void build(int &x,int h,int t)
  {
    x=travel[mid];
    if (h==t)
    {
      siz[x]=cnt[x]=1;
      ls[x]=rs[x]=0;
      return;
    }
    if (h<mid) build(ls[x],h,mid-1); else ls[x]=0;
    build(rs[x],mid+1,t);
    siz[x]=siz[ls[x]]+siz[rs[x]]+1;
    cnt[x]=cnt[ls[x]]+cnt[rs[x]]+1;
  }
  void rebuild(int &x)
  {
    t1=0; dfs(x);
    if (t1) build(x,1,t1);
    else x=0;
  }
  void insert(int &x,int k)
  {
    if (!x)
    {
      x=s[top--]; v[x]=k;
      siz[x]=cnt[x]=f[x]=1;
      ls[x]=rs[x]=0;
      return;
    }
    siz[x]++; cnt[x]++;
    if (k<=v[x]) insert(ls[x],k);
    else insert(rs[x],k);
       if ((double)max(siz[ls[x]],siz[rs[x]])>(double)siz[x]*alpha)
    {
      rebuild(x);
    } 
  }
  void del(int x,int k)
  {
    siz[x]--;
    if (f[x]&&k==v[x])
    {
      f[x]=0; return;
    }
    if (k<=v[x]) del(ls[x],k);
    else del(rs[x],k);
  }
  void del(int k)
  {
    int now=rt;
    while (now)
    {
      siz[now]--;
      if (f[now]&&k==siz[ls[now]]+1)
      {
        f[now]=0; 
        return;
      }
      if (k<=siz[ls[now]]) now=ls[now];
      else k-=siz[ls[now]]+f[now],now=rs[now];
    }
  }
  void delete2(int x)
  {
    del(x);
   if ((double)siz[rt]<(double) alpha*cnt[rt]) rebuild(rt);
  }
  int rank(int x)
  {
    int now=rt,ans=1;
    while (now)
    {
      if (v[now]>=x) now=ls[now];
      else ans+=siz[ls[now]]+f[now],now=rs[now];
    }
    return(ans);
  }
  int get_kth(int x)
  {
    int now=rt;
    while (now)
    {
      if (f[now]&&x==siz[ls[now]]+1) return(v[now]);
      if (siz[ls[now]]>=x) now=ls[now];
      else x-=siz[ls[now]]+f[now],now=rs[now];
    }
  }
}S;
int main()
{
  freopen("1.in","r",stdin);
  freopen("1.out","w",stdout);
  ios::sync_with_stdio(false); 
  cin>>n;
  dep(i,4000000,1) s[++top]=i;
  rep(i,1,n)
  {
   // cout<<i<<endl; 
    int kk,x;
    cin>>kk>>x;
    if (kk==1)
    {
      S.insert(rt,x);
    }
    if (kk==2)
    {
      S.delete2(S.rank(x));
    }
    if (kk==3)
    {
      cout<<S.rank(x)<<endl; 
    }
    if (kk==4)
    {
      cout<<S.get_kth(x)<<endl;
    }
    if (kk==5)
    {
      cout<<S.get_kth(S.rank(x)-1)<<endl;
    }
    if (kk==6)
    {
      cout<<S.get_kth(S.rank(x+1))<<endl;
    }
  }
  return 0; 
}
  

 

https://zhuanlan.zhihu.com/p/21263304

posted @ 2018-09-26 00:18  尹吴潇  阅读(150)  评论(0编辑  收藏  举报