|
6#
楼主 |
发表于 2020-4-23 18:36:37
|
只看该作者
结合上面所有的代码,3369的做法如下,交上去,顺利AC.
- #include<bits/stdc++.h>
- using namespace std;
- const int inf=99999999;
- const int N=100100;
- struct node
- {
- int val,cnt;
- int fa,s[2],sz; ///s0s1左右儿子
- } a[N];
- int n, tot, root;
- void ArrayPr() /// 调试监视使用
- {
- cout<<endl<<" i ";
- for (int i=1; i<=tot; i++) cout<<setw(3)<<i;
- cout<<endl<<"val ";
- for (int i=1; i<=tot; i++) cout<<setw(3)<<a[i].val;
- cout<<endl<<"cnt ";
- for (int i=1; i<=tot; i++) cout<<setw(3)<<a[i].cnt;
- cout<<endl<<" s0 ";
- for (int i=1; i<=tot; i++) cout<<setw(3)<<a[i].s[0];
- cout<<endl<<" s1 ";
- for (int i=1; i<=tot; i++) cout<<setw(3)<<a[i].s[1];
- cout<<endl<<" fa ";
- for (int i=1; i<=tot; i++) cout<<setw(3)<<a[i].fa;
- cout<<endl<<" sz ";
- for (int i=1; i<=tot; i++) cout<<setw(3)<<a[i].sz;
- cout<<endl;
- }
- void BSTPr(int rt) ///中序输出以rt为根的BST
- {
- if (a[rt].s[0]>0) BSTPr(a[rt].s[0]);
- if (a[rt].cnt>0) cout<<a[rt].val<<' '<<a[rt].cnt<<endl;
- if (a[rt].s[1]>0) BSTPr(a[rt].s[1]);
- }
- void pushdown(int rt) ///类似线段树网上调整
- {
- ///暂时无用
- }
- void pushup(int rt) ///类似线段树网上调整
- {
- int l=a[rt].s[0], r=a[rt].s[1];
- a[rt].sz=a[l].sz+a[r].sz+a[rt].cnt;
- }
- int Son(int x)///判断x是L还是R儿子
- {
- int y=a[x].fa;
- return a[y].s[1]==x;
- }
- void R(int x)
- {
- int y=a[x].fa;
- int z=a[y].fa;
- int k=Son(x);
- int v=a[x].s[k^1];///v是x另外一边的儿子将要被挂在y下面
- pushdown(x),pushdown(y);///下传
- a[y].s[k]=v,a[v].fa=y;///v挂在y下 要是v=0这里省略了
- a[z].s[Son(y)]=x,a[x].fa=z;///x挂在z下
- a[x].s[k^1]=y,a[y].fa=x;///y挂在x下
- /// 这三步需要画图理解
- pushup(y),pushup(x);///上传,注意顺序
- }
- inline void Splay(int x,int rt=root) ///把x旋到rt的位置 默认rt是根
- {
- rt=a[rt].fa;
- int y,z;
- while(a[x].fa!=rt) /// y==rt就到位
- {
- y=a[x].fa,z=a[y].fa;;
- if(z!=rt)
- if(Son(x)==Son(y))R(y); /// 一字
- else R(x);
- R(x);
- }
- if(rt==0)root=x;
- }
- int Find(int rt,int x) /// 找到x对应的a[rt]
- {
- if (a[rt].val==x)
- {
- Splay(rt,root);
- return rt;
- }
- int k=a[rt].val<x; /// k=0表示左子树中去1表示去右子树
- if (a[rt].s[k]>0) return Find(a[rt].s[k],x);
- else return 0;
- }
- void Ins(int rt, int x) /// 在rt子树中插入x
- {
- a[rt].sz++;
- if(a[rt].val==x) a[rt].cnt++;
- else
- {
- int k=(a[rt].val<x);/// k=0表示左子树中去1表示去右子树
- if (a[rt].s[k]==0)
- {
- a[rt].s[k]=++tot;
- a[tot].s[0]=a[tot].s[1]=0;
- a[tot].val=x;
- a[tot].fa=rt;
- a[tot].cnt=a[tot].sz=1;
- Splay(tot,root);
- }
- else
- Ins(a[rt].s[k],x);
- }
- }
- void Del(int x) //删除节点
- {
- int rt=Find(root,x);///找到对应的rt
- if(rt==0) return;
- a[rt].sz--;
- if(a[rt].cnt>1) a[rt].cnt--;
- else if(a[rt].s[0]==0) /// 没有左子树
- {
- root=a[rt].s[1];
- a[root].fa=0;
- }
- else
- {
- int p,l,r;
- l=a[rt].s[0];
- r=a[rt].s[1];
- /// 左子树里面去找最右的儿子
- p=l;
- while(a[p].s[1]>0) p=a[p].s[1];
- Splay(p,l); ///转上来作为根的左子树
- /// 因为最大,没有右子树,把他作为新根
- a[p].s[1]=r; ///rt的右儿子接上去
- a[r].fa=p;
- a[root=p].fa=0;;/// 新根
- pushup(p);
- }
- ///要不要回收?
- }
- int Rank(int x) ///在RT子树中比x小的数 +1
- {
- int rt=Find(root,x);
- int l=a[rt].s[0];
- return a[l].sz;/// 包含那个-inf 所以不需要+1
- }
- int Getkth(int rt, int x) ///在RT子树中找第k小
- {
- int l=a[a[rt].s[0]].sz; /// RT的左儿子下的个数
- if(l+1<=x && x<=l+a[rt].cnt) return a[rt].val;
- if(l+1>x) return Getkth(a[rt].s[0], x); ///左儿子里去找
- if(l+a[rt].cnt<x) return Getkth(a[rt].s[1], x-(l+a[rt].cnt));
- }
- int Pre(int rt, int x)
- {
- int p=rt, ans;
- while(p>0)
- {
- if(x<=a[p].val) p=a[p].s[0];
- else
- {
- ans=p;
- p=a[p].s[1];
- }
- }
- return ans;
- }
- int Suc(int rt, int x)
- {
- int p=rt, ans;
- while(p>0)
- {
- if(a[p].val<=x) p=a[p].s[1];
- else
- {
- ans = p;
- p=a[p].s[0];
- }
- }
- return ans;
- }
- int main()
- {
- ///freopen("3369.in","r",stdin);
- ///freopen("3369.out","w",stdout);
- int x,opt;
- cin>>n;
- //插入-inf和inf
- root=1;
- tot=2;
- a[1].val=-inf,a[1].s[0]=0,a[1].s[1]=2,a[1].fa=0;
- a[2].val= inf,a[2].s[0]=0,a[2].s[1]=0,a[2].fa=1;
- a[1].sz=2,a[2].sz=1;
- a[1].cnt=a[2].cnt=1;
- while(n--)
- {
- cin>>opt>>x;
- if(opt==1) Ins(root, x);
- if(opt==2) Del(x);
- if(opt==3) cout<<Rank(x)<<endl;
- if(opt==4) cout<<Getkth(root, x+1)<<endl;
- if(opt==5) cout<<a[Pre(root, x)].val<<endl;
- if(opt==6) cout<<a[Suc(root, x)].val<<endl;
- }
- return 0;
- }
- /*
- 40
- 1 3 7 5 9 2 8 4 6 0
- 11 13 17 15 19 12 18 14 16 10
- 31 33 37 35 39 32 38 34 36 30
- 11 13 17 15 19 12 18 14 16 10
- */
复制代码 |
|