Bzoj3224 / Tyvj 1728 普通替罪羊树

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 12015  Solved: 5136

Description

您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)

Input

第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)

Output

对于操作3,4,5,6每行输出一个数,表示对应答案

Sample Input

10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598

Sample Output

106465
84185
492737

HINT

 

1.n的数据范围:n<=100000

2.每个数的数据范围:[-2e9,2e9]

 

Source

 

替罪羊树

曾经我一直以为替罪羊树就是不平衡的时候拍扁了重建……

真是拿衣服

 

从yhx那里get了神奇的删点方法:找到它的前驱pre,用pre代替它←虽然只有一句话,但这是整道题最麻烦的地方

http://blog.csdn.net/sdfzyhx/article/details/70212142

代码里同时用到了st,top,st2,top2两组变量,写的时候我还在想这样会不会写混,事实证明果然写混调了半天…… 

 

  1 /*by SilverN*/
  2 #include<algorithm>
  3 #include<iostream>
  4 #include<cstring>
  5 #include<cstdio>
  6 #include<cmath>
  7 #include<vector>
  8 using namespace std;
  9 const int mxn=120010;
 10 int read(){
 11     int x=0,f=1;char ch=getchar();
 12     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 13     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
 14     return x*f;
 15 }
 16 struct node{
 17     int l,r;
 18     int val,sz;
 19     int cnt;
 20     bool operator < (const node b)const{
 21         return val<b.val;
 22     }
 23 }t[mxn],vt[mxn];
 24 int rot=0;
 25 int sz=0,cnt=0;
 26 int st[mxn],top=0;
 27 int flag=0,faf;
 28 int newnode(){
 29     int res=0;
 30     if(top)res=st[top--];
 31     else res=++cnt;
 32     t[res].sz=t[res].l=t[res].r=t[res].cnt=0;
 33     return res;
 34 }
 35 void pushup(int x){
 36     t[x].sz=t[t[x].l].sz+t[t[x].r].sz+t[x].cnt;return;
 37 }
 38 void Build(int l,int r,int &rt){
 39     if(l>r){rt=0;return;}
 40     int mid=(l+r)>>1;
 41     rt=newnode();
 42     t[rt].val=vt[mid].val;
 43     t[rt].cnt=vt[mid].cnt;
 44     t[rt].sz=t[rt].cnt;
 45     Build(l,mid-1,t[rt].l);
 46     Build(mid+1,r,t[rt].r);
 47     pushup(rt);
 48     return;
 49 }
 50 void insert(int &rt,int x){
 51     if(!rt){
 52         rt=newnode();
 53         t[rt].val=x;
 54         t[rt].cnt=t[rt].sz=1;
 55         return;
 56     }
 57     t[rt].sz++;
 58     if(t[rt].val==x){
 59         t[rt].cnt++;
 60         return;
 61     }
 62     if(x<t[rt].val)insert(t[rt].l,x);
 63     else insert(t[rt].r,x);
 64     if(t[t[rt].l].sz/(double)t[rt].sz>0.666)flag=rt;
 65     if(flag==t[rt].l || flag==t[rt].r)faf=rt;
 66     pushup(rt);
 67     return;
 68 }
 69 void del(int rt){
 70     if(!rt)return;
 71     vt[++sz]=t[rt];
 72     st[++top]=rt;
 73     del(t[rt].l);
 74     del(t[rt].r);
 75     return;
 76 }
 77 int pre(int rt,int x){
 78     int res=-2e9-1,pos=0;
 79     while(rt){
 80         if(t[rt].val>=x){
 81             rt=t[rt].l;
 82         }
 83         else{
 84             if(t[rt].val>res){res=t[rt].val;pos=rt;}
 85             rt=t[rt].r;
 86         }
 87     }
 88     return pos;
 89 }
 90 int sub(int rt,int x){
 91     int res=2e9+1,pos=0;
 92     while(rt){
 93         if(t[rt].val<=x){
 94             rt=t[rt].r;
 95         }
 96         else{
 97             if(t[rt].val<res){res=t[rt].val;pos=rt;}
 98             rt=t[rt].l;
 99         }
100     }
101     return pos;
102 }
103 int st2[mxn],top2=0,fafa;
104 void Q_erase(int &rt,int x){
105 //    if(!rt && x==299181)while(1);
106     if(t[rt].val==x){
107         t[rt].cnt--;
108         t[rt].sz--;
109         if(!t[rt].cnt){
110             if(t[rt].l*t[rt].r==0){rt=t[rt].l+t[rt].r;return;}
111             int p=t[rt].l;
112             while(t[p].r){st2[++top2]=p;p=t[p].r;}
113             if(top2){
114                 t[st2[top2]].r=t[p].l;
115                 pushup(st2[top2]);
116                 t[p].l=t[rt].l;
117                 t[p].r=t[rt].r;
118                 while(top2)pushup(st2[top2--]);
119             }
120             else t[p].r=t[rt].r;
121             if(fafa){
122                 if(t[fafa].l==rt) t[fafa].l=p;
123                 else t[fafa].r=p;
124             }
125             pushup(p);
126             pushup(t[rt].l);
127             rt=p;
128         }
129         pushup(fafa);
130         return;
131     }
132     fafa=rt;
133     if(x<t[rt].val)Q_erase(t[rt].l,x);
134     else Q_erase(t[rt].r,x);
135     pushup(rt);
136     return;
137 }
138 int Q_rank(int rt,int x){
139     int res=0;
140     while(rt){
141         if(t[rt].val<x){
142             res+=t[t[rt].l].sz+t[rt].cnt;
143             rt=t[rt].r;
144         }
145         else rt=t[rt].l;
146     }
147     return res+1;
148 }
149 int Q_num(int rt,int k){
150     int res=0;
151     while(rt){
152         if(t[t[rt].l].sz>=k){
153             res=t[rt].val;
154             rt=t[rt].l;
155         }
156         else if(t[t[rt].l].sz+t[rt].cnt>=k)return t[rt].val;
157             else k-=t[t[rt].l].sz+t[rt].cnt,rt=t[rt].r;
158     }
159     return res;
160 }
161 void Debug(int x){
162     if(!x)return;
163     printf("#%d: v:%d l:%d r:%d sz:%d cnt:%d\n",
164         x,t[x].val,t[x].l,t[x].r,t[x].sz,t[x].cnt);
165     Debug(t[x].l);Debug(t[x].r);
166 }
167 int n;
168 int main(){
169 //    freopen("in.txt","r",stdin);
170 //    freopen("out.out","w",stdout);
171     int i,j;
172     n=read();
173     int op,x;
174     int tct=0;
175     while(n--){
176         op=read();x=read();
177         if(op!=1)tct++;
178         switch(op){
179             case 1:{
180                 flag=faf=0;sz=0;
181                 insert(rot,x);
182                 if(flag){
183                     del(flag);
184                     sort(vt+1,vt+sz+1);
185                     if(flag==rot)Build(1,sz,rot);
186                     else Build(1,sz,(t[faf].l==flag)?t[faf].l:t[faf].r);
187                 }
188                 break;
189             }
190             case 2:{fafa=0;Q_erase(rot,x);break;}
191             case 3:{
192                 int ans=Q_rank(rot,x);
193                 printf("%d\n",ans);
194                 break;
195             }
196             case 4:{
197                 int ans=Q_num(rot,x);
198                 printf("%d\n",ans);
199                 break;
200             }
201             case 5:{
202                 int res=pre(rot,x);
203                 printf("%d\n",t[res].val);
204                 break;
205             }
206             case 6:{
207                 int res=sub(rot,x);
208                 printf("%d\n",t[res].val);
209                 break;
210             }
211             case 7:{
212                 Debug(rot);
213                 break;
214             }
215         }
216     }
217     return 0;
218 }

 

转载于:https://www.cnblogs.com/SilverNebula/p/6728686.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值