维护集合Ⅰ【无旋Treap数组模板】
2017-10-07 11:39
288 查看
无旋treap模板题
维护一个多重集S ,初始为空,有以下几种操作:
1. 把 x 加入 S。
2. 删除 S 中的一个 x ,保证删除的 x 一定存在。
3. 求 S 中第 k 小。
4. 求 S 中有多少个元素小于x。
5. 求 S 中小于 x 的最大数。
6. 求 S 中大于 x 的最小数。
操作共 n 次 。
接下来 n 行,每行为以下几种格式之一 :
0 x,把 x(0 ≤x≤10^9 ) 加入 S 。
1 x,删除 S 中的一个 x,保证删除的数在 S 中一定存在 。
2 k,求 S 中第 k(1≤k≤|S|)小 。
3 x,求 S 中有多少个数小于 x(0≤x≤10^9) 。
4 x,求S 中小于 x(0≤x≤10^9 )的最大数,如果不存在,输出 -1。
5 x,求S 中大于 x(0≤x≤10^9 )的最小数,如果不存在,输出 -1。
5
0 3
0 4
2 2
1 4
3 3
输出
4
0
题目描述
如未特别说明,以下所有数据均为整数。维护一个多重集S ,初始为空,有以下几种操作:
1. 把 x 加入 S。
2. 删除 S 中的一个 x ,保证删除的 x 一定存在。
3. 求 S 中第 k 小。
4. 求 S 中有多少个元素小于x。
5. 求 S 中小于 x 的最大数。
6. 求 S 中大于 x 的最小数。
操作共 n 次 。
输入格式
第一行一个整数 n(1≤n≤3×10^5 ) ,表示共有 n 次操作 。接下来 n 行,每行为以下几种格式之一 :
0 x,把 x(0 ≤x≤10^9 ) 加入 S 。
1 x,删除 S 中的一个 x,保证删除的数在 S 中一定存在 。
2 k,求 S 中第 k(1≤k≤|S|)小 。
3 x,求 S 中有多少个数小于 x(0≤x≤10^9) 。
4 x,求S 中小于 x(0≤x≤10^9 )的最大数,如果不存在,输出 -1。
5 x,求S 中大于 x(0≤x≤10^9 )的最小数,如果不存在,输出 -1。
输出格式
对于每次询问,输出单独一行表示答案。样例数据 1
输入 [复制]5
0 3
0 4
2 2
1 4
3 3
输出
4
0
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<ctime> using namespace std; int getint() { int i=0,f=1;char c; for(c=getchar();(c<'0'||c>'9')&&c!='-';c=getchar()); if(c=='-')c=getchar(),f=-1; for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0'; return i*f; } const int N=300005; int n,root,L,R; int tot,val ,pri ,size ,son [2]; int upt(int u) { size[u]=size[son[u][0]]+size[son[u][1]]+1; return u; } int merge(int u,int v) { if(!u)return upt(v); if(!v)return upt(u); if(pri[u]<pri[v]) { son[u][1]=merge(son[u][1],v); return upt(u); } else { son[v][0]=merge(u,son[v][0]); return upt(v); } } void Split(int u,int v,int &L,int &R) { if(!u) { L=R=0; return; } if(val[u]<=v) { Split(son[u][1],v,L,R); son[u][1]=0,upt(u); L=merge(u,L); } else { Split(son[u][0],v,L,R); son[u][0]=0,upt(u); R=merge(R,u); } } void Split_Kth(int u,int kth,int &L,int &R) { if(!u) { L=R=0; return; } if(size[son[u][0]]<kth) { Split_Kth(son[u][1],kth-size[son[u][0]]-1,L,R); son[u][1]=0,upt(u); L=merge(u,L); } else { Split_Kth(son[u][0],kth,L,R); son[u][0]=0,upt(u); R=merge(R,u); } } void Insert(int v) { L=R=0; Split(root,v,L,R); val[++tot]=v,pri[tot]=rand(); root=merge(merge(L,tot),R); } void Delete(int v) { L=R=0; int p=0,q=0; Split(root,v,L,R); Split_Kth(L,size[L]-1,p,q); root=merge(p,R); } void Find_Kth(int k) { L=R=0; Split_Kth(root,k,L,R); int pos=L; while(son[pos][1])pos=son[pos][1]; cout<<val[pos]<<'\n'; root=merge(L,R); } void Lower_count(int v) { L=R=0; Split(root,v-1,L,R); cout<<size[L]<<'\n'; root=merge(L,R); } void Upper_bound(int v) { L=R=0; Split(root,v-1,L,R); if(!L) { cout<<-1<<'\n'; return; } int pos=L; while(son[pos][1])pos=son[pos][1]; cout<<val[pos]<<'\n'; root=merge(L,R); } void Lower_bound(int v) { L=R=0; Split(root,v,L,R); if(!R) { cout<<-1<<'\n'; return; } int pos=R; while(son[pos][0])pos=son[pos][0]; cout<<val[pos]<<'\n'; root=merge(L,R); } int main() { //freopen("lx.in","r",stdin); //freopen("lx.out","w",stdout); int op,x; srand(time(0)); n=getint(); while(n--) { op=getint(),x=getint(); if(op==0)Insert(x); if(op==1)Delete(x); if(op==2)Find_Kth(x); if(op==3)Lower_count(x); if(op==4)Upper_bound(x); if(op==5)Lower_bound(x); } return 0; }
相关文章推荐
- Treap 维护集合模板
- P3368 【模板】树状数组 2(树状数组维护差分序列)
- 无旋treap模板 数组版
- 【模板】treap(数组)
- [模板] 树堆 - Treap的指针和数组实现及一些例题
- 康托展开模板(树状数组维护)O (n log n)
- 静态数组Treap(用随机数维护的二叉搜索树)
- 数组splay ------ luogu P3369 【模板】普通平衡树(Treap/SBT)
- 【luogu3374】模板 树状数组 1
- 第五讲.字典,集合,数组排序(快速排序,冒泡,默认排序)(源代码)
- poj 2774 后缀数组模板
- Scala学习教程笔记一之基础语法,条件控制,循环控制,函数,数组,集合
- P3374 【模板】树状数组 1
- 增强for循环不能给集合或者数组赋值
- 字典,集合,数组排序
- smarty模板中判断数组为空方法
- 后缀数组模板
- 递归求集合子集(两种方法实现(数组,链表))
- C#学习笔记集合类型之数组(3)
- 文章标题 Java 数组和集合