[洛谷P3369] 普通平衡树 Treap & Splay

这个就是存一下板子......

题目传送门

Treap的实现应该是比较正经的。

插入删除前驱后继排名什么的都是平衡树的基本操作。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<cstdlib>
  5 using namespace std;
  6 
  7 int n,root,tot;
  8 
  9 struct treap
 10 {
 11     int ls,rs,v,rd,sz,h;
 12 }t[100005];
 13 
 14 void update(int p)
 15 {
 16     t[p].sz=t[t[p].ls].sz+t[t[p].rs].sz+t[p].h;
 17 }
 18 
 19 void zig(int &p)
 20 {
 21     int r=t[p].rs;
 22     t[p].rs=t[r].ls;
 23     t[r].ls=p;
 24     t[r].sz=t[p].sz;
 25     update(p);
 26     p=r;
 27 }
 28 
 29 void zag(int &p)
 30 {
 31     int l=t[p].ls;
 32     t[p].ls=t[l].rs;
 33     t[l].rs=p;
 34     t[l].sz=t[p].sz;
 35     update(p);
 36     p=l;
 37 }
 38 
 39 void insert(int &p,int val)
 40 {
 41     if(p==0)
 42     {
 43         tot++;
 44         p=tot;
 45         t[p].sz=t[p].h=1;
 46         t[p].v=val;
 47         t[p].rd=rand();
 48         return;
 49     }
 50     t[p].sz++;
 51     if(t[p].v==val)t[p].h++;
 52     else if(t[p].v<val)
 53     {
 54         insert(t[p].rs,val);
 55         if(t[p].rd>t[t[p].rs].rd)zig(p);
 56     }else
 57     {
 58         insert(t[p].ls,val);
 59         if(t[p].rd>t[t[p].ls].rd)zag(p);
 60     }
 61 }
 62 
 63 void del(int &p,int val)
 64 {
 65     if(!p)return;
 66     if(t[p].v==val)
 67     {
 68         if(t[p].h>1)
 69         {
 70             t[p].h--;
 71             t[p].sz--;
 72             return;
 73         }
 74         if(t[p].ls*t[p].rs==0)p=t[p].ls+t[p].rs;
 75         else if(t[t[p].ls].rd<t[t[p].rs].rd)
 76         {
 77             zag(p);
 78             del(p,val);
 79         }else
 80         {
 81             zig(p);
 82             del(p,val);
 83         }
 84     }else if(t[p].v<val)
 85     {
 86         t[p].sz--;
 87         del(t[p].rs,val);
 88     }else
 89     {
 90         t[p].sz--;
 91         del(t[p].ls,val);
 92     }
 93 }
 94 
 95 int qrank(int p,int val)
 96 {
 97     if(!p)return 0;
 98     if(t[p].v==val)return t[t[p].ls].sz+1;
 99     else if(t[p].v<val)return t[t[p].ls].sz+t[p].h+qrank(t[p].rs,val);
100     else return qrank(t[p].ls,val);
101 }
102 
103 int qnum(int p,int rk)
104 {
105     if(!p)return 0;
106     int lsz=t[t[p].ls].sz+t[p].h;
107     if(rk<=t[t[p].ls].sz)return qnum(t[p].ls,rk);
108     else if(rk>lsz)return qnum(t[p].rs,rk-lsz);
109     else return t[p].v;
110 }
111 
112 void pre(int p,int val,int &ans)
113 {
114     if(!p)return;
115     if(t[p].v<val)
116     {
117         ans=p;
118         pre(t[p].rs,val,ans);
119     }else pre(t[p].ls,val,ans);
120 }
121 
122 void post(int p,int val,int &ans)
123 {
124     if(!p)return;
125     if(t[p].v>val)
126     {
127         ans=p;
128         post(t[p].ls,val,ans);
129     }else post(t[p].rs,val,ans);
130 }
131 
132 int main()
133 {
134     scanf("%d",&n);
135     int op,x;
136     while(n--)
137     {
138         scanf("%d%d",&op,&x);
139         if(op==1)insert(root,x);
140         if(op==2)del(root,x);
141         if(op==3)printf("%d
",qrank(root,x));
142         if(op==4)printf("%d
",qnum(root,x));
143         if(op==5){int r=0;pre(root,x,r);printf("%d
",t[r].v);}
144         if(op==6){int r=0;post(root,x,r);printf("%d
",t[r].v);}
145     }
146     return 0;
147 }

今天突然想用splay写一下,复习复习。

之后发现第12个点T飞了......

下载输入数据之后,发现这个数据是构造的,依次插入了1~50000这50000个数。

用cfree调试了一下,发现这样会在splay上弄出一个长长的链。

可能是我太菜了,但是我用了两种方法(具体见代码)都会出链导致T飞。

最后为了男人的尊严,我用了一些玄学(随机)算法总算A掉了。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<cstdlib>
  5 #define id(x) (s[f[x]][1]==x)
  6 using namespace std;
  7 
  8 int n,root=2,tot=2;
  9 int f[100005],s[100005][2];
 10 int v[100005],h[100005],sz[100005];
 11 
 12 void pushup(int p)
 13 {
 14     sz[p]=sz[s[p][0]]+sz[s[p][1]]+h[p];
 15 }
 16 
 17 void rotate(int p)
 18 {
 19     int k=id(p);
 20     int fa=f[p];
 21     s[fa][k]=s[p][!k];
 22     s[p][!k]=fa;
 23     s[f[fa]][id(fa)]=p;
 24     f[p]=f[fa];
 25     f[fa]=p;
 26     f[s[fa][k]]=fa;
 27     pushup(fa);
 28     pushup(p);
 29 }
 30 
 31 void splay(int p,int g)
 32 {
 33     while(f[p]!=g)
 34     {
 35         int fa=f[p];
 36         if(f[fa]==g)
 37         {
 38             rotate(p);
 39             break;
 40         }
 41         if(id(p)^id(fa))rotate(p);
 42         else rotate(fa);
 43         rotate(p);
 44     }
 45     if(!g)root=p;
 46 }
 47 
 48 void pre(int p,int val,int &ans)
 49 {
 50     if(!p)return;
 51     if(v[p]>=val)pre(s[p][0],val,ans);
 52     else ans=p,pre(s[p][1],val,ans);
 53 }
 54 
 55 void post(int p,int val,int &ans)
 56 {
 57     if(!p)return;
 58     if(v[p]<=val)post(s[p][1],val,ans);
 59     else ans=p,post(s[p][0],val,ans);
 60 }
 61 
 62 int qrank(int p,int num)
 63 {
 64     if(!p)return 0;
 65     if(num<v[p])return qrank(s[p][0],num);
 66     if(num==v[p])return sz[s[p][0]]+1;
 67     return sz[s[p][0]]+h[p]+qrank(s[p][1],num);
 68 }
 69 
 70 int qnum(int p,int rk)
 71 {
 72     if(!p)return 0;
 73     int lm=sz[s[p][0]]+h[p];
 74     if(rk<=sz[s[p][0]])return qnum(s[p][0],rk);
 75     if(rk>lm)return qnum(s[p][1],rk-lm);
 76     return v[p];
 77 }
 78 
 79 int d[100005];
 80 
 81 void ins(int val)
 82 {
 83     /*int bef,aft;
 84     pre(root,val,bef);
 85     post(root,val,aft);
 86     splay(bef,0);
 87     splay(aft,root);
 88     int gp=s[root][1];
 89     if(!s[gp][0])
 90     {
 91         s[gp][0]=++tot;
 92         f[tot]=gp;
 93         v[tot]=val;
 94     }
 95     h[s[gp][0]]++,sz[s[gp][0]]++;
 96     pushup(gp),pushup(root);*/
 97     
 98     int p=root,fa=0;
 99     while(p&&v[p]!=val)
100     {
101         fa=p;
102         p=s[p][val>v[p]];
103     }
104     if(!p)
105     {
106         p=++tot;
107         s[fa][val>v[fa]]=p;
108         sz[p]=1;
109         f[p]=fa;
110         v[p]=val;
111     }
112     h[p]++;
113     splay(p,0);
114     int k=rand()%tot+1;
115     while(d[k])k=rand()%tot+1;
116     splay(k,0);
117 }
118 
119 void del(int val)
120 {
121     int bef,aft;
122     pre(root,val,bef);
123     post(root,val,aft);
124     splay(bef,0);
125     splay(aft,root);
126     int gp=s[root][1];
127     h[s[gp][0]]--;
128     sz[s[gp][0]]--;
129     if(!h[s[gp][0]])d[s[gp][0]]=1,s[gp][0]=0;
130     pushup(gp),pushup(root);
131 }
132 
133 int main()
134 {
135     scanf("%d",&n);
136     f[1]=2;
137     s[2][0]=1;
138     v[1]=-0x3f3f3f3f;
139     v[2]=0x3f3f3f3f;
140     h[1]=h[2]=sz[1]=1;
141     sz[2]=2;
142     for(int i=1;i<=n;i++)
143     {
144         int op,x;
145         scanf("%d%d",&op,&x);
146         if(op==1)ins(x);
147         if(op==2)del(x);
148         if(op==3){int rk=qrank(root,x)-1;printf("%d
",rk);}
149         if(op==4){int num=qnum(root,x+1);printf("%d
",num);}
150         if(op==5){int pos;pre(root,x,pos);printf("%d
",v[pos]);}
151         if(op==6){int pos;post(root,x,pos);printf("%d
",v[pos]);}
152     }
153     return 0;
154 }
原文地址:https://www.cnblogs.com/eternhope/p/9735305.html