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

  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 }
时间: 2024-09-30 09:00:43

Bzoj3224 / Tyvj 1728 普通替罪羊树的相关文章

BZOJ3224: Tyvj 1728 普通平衡树[treap]

3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 9046  Solved: 3840[Submit][Status][Discuss] Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数,因输出最小的排名)4. 查询排名为x的数5. 求x的前驱(前驱定义为小

bzoj3224 Tyvj 1728 普通平衡树

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,

【权值线段树】bzoj3224 Tyvj 1728 普通平衡树

一个板子. #include<cstdio> #include<algorithm> using namespace std; #define N 100001 struct Data { int v,p; }t[N]; bool cmp(const Data &a,const Data &b) { return a.v<b.v; } int T[N<<2],op[N],a[N],n,ma[N],e; void Update(int p,int v

【权值分块】bzoj3224 Tyvj 1728 普通平衡树

权值分块和权值线段树的思想一致,离散化之后可以代替平衡树的部分功能. 部分操作的时间复杂度: 插入 删除 全局排名 全局K大 前驱 后继 全局最值 O(1) O(1) O(sqrt(n)) O(sqrt(n)) O(sqrt(n)) O(sqrt(n)) O(sqrt(n)) 当然,因为要离散化,所以只能离线. 代码很短,很快,比我的Splay短一倍,快一倍,现在在bzoj上rank6. 1 #include<cstdio> 2 #include<algorithm> 3 #inc

bzoj3224: Tyvj 1728 普通平衡树(打个splay暖暖手)

(其实今天好热啊? 题目大意:插入,删除,k小,前驱后继,数的排名. splay和treap裸题...过几天补个treap的 splay: #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> using namespace std; const int extar[3]={0,2147483647,-2147483647}; int fa[100010],count[

【Splay】bzoj3224 Tyvj 1728 普通平衡树

#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> using namespace std; #define maxn 1000000 #define INF 2147483647 int n,fa[maxn],val[maxn],c[maxn][2],root,tot,siz[maxn],cnt[maxn]; void Maintain(int x) { siz

[TYVJ1728/BZOJ3224]普通平衡树-替罪羊树

Problem 普通平衡树 Solution 本题是裸的二叉平衡树.有很多种方法可以实现.这里打的是替罪羊树模板. 此题极其恶心. 前驱后继模块需要利用到rank模块来换一种思路求. 很多细节的地方容易炸.我拿数据调了很久才A. (delt()删除模块其实是不需要重建的,不影响时间复杂度) 替罪羊树具体详见此篇知乎:替罪羊树 AC Code 1 #include "iostream" 2 #include "cstdio" 3 #define alpha 0.7 4

3224: Tyvj 1728 普通平衡树

3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2566  Solved: 1031[Submit][Status] Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数,因输出最小的排名)4. 查询排名为x的数5. 求x的前驱(前驱定义为小于x,且最大的数)

bzoj 3224: Tyvj 1728 普通平衡树.

3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 15114  Solved: 6570[Submit][Status][Discuss] Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数,因输出最小的排名)4. 查询排名为x的数5. 求x的前驱(前驱定义为