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
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
Sample Output
84185
492737
HINT
Source
替罪羊树
曾经我一直以为替罪羊树就是不平衡的时候拍扁了重建……
真是拿衣服
从yhx那里get了神奇的删点方法:找到它的前驱pre,用pre代替它←虽然只有一句话,但这是整道题最麻烦的地方
http://blog.csdn.net/sdfzyhx/article/details/70212142
代码里同时用到了st,top,st2,top2两组变量,写的时候我还在想这样会不会写混,事实证明果然写混调了半天……
/*by SilverN*/
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<vector>
using namespace std;
const int mxn=;
int read(){
int x=,f=;char ch=getchar();
while(ch<'' || ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>='' && ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
struct node{
int l,r;
int val,sz;
int cnt;
bool operator < (const node b)const{
return val<b.val;
}
}t[mxn],vt[mxn];
int rot=;
int sz=,cnt=;
int st[mxn],top=;
int flag=,faf;
int newnode(){
int res=;
if(top)res=st[top--];
else res=++cnt;
t[res].sz=t[res].l=t[res].r=t[res].cnt=;
return res;
}
void pushup(int x){
t[x].sz=t[t[x].l].sz+t[t[x].r].sz+t[x].cnt;return;
}
void Build(int l,int r,int &rt){
if(l>r){rt=;return;}
int mid=(l+r)>>;
rt=newnode();
t[rt].val=vt[mid].val;
t[rt].cnt=vt[mid].cnt;
t[rt].sz=t[rt].cnt;
Build(l,mid-,t[rt].l);
Build(mid+,r,t[rt].r);
pushup(rt);
return;
}
void insert(int &rt,int x){
if(!rt){
rt=newnode();
t[rt].val=x;
t[rt].cnt=t[rt].sz=;
return;
}
t[rt].sz++;
if(t[rt].val==x){
t[rt].cnt++;
return;
}
if(x<t[rt].val)insert(t[rt].l,x);
else insert(t[rt].r,x);
if(t[t[rt].l].sz/(double)t[rt].sz>0.666)flag=rt;
if(flag==t[rt].l || flag==t[rt].r)faf=rt;
pushup(rt);
return;
}
void del(int rt){
if(!rt)return;
vt[++sz]=t[rt];
st[++top]=rt;
del(t[rt].l);
del(t[rt].r);
return;
}
int pre(int rt,int x){
int res=-2e9-,pos=;
while(rt){
if(t[rt].val>=x){
rt=t[rt].l;
}
else{
if(t[rt].val>res){res=t[rt].val;pos=rt;}
rt=t[rt].r;
}
}
return pos;
}
int sub(int rt,int x){
int res=2e9+,pos=;
while(rt){
if(t[rt].val<=x){
rt=t[rt].r;
}
else{
if(t[rt].val<res){res=t[rt].val;pos=rt;}
rt=t[rt].l;
}
}
return pos;
}
int st2[mxn],top2=,fafa;
void Q_erase(int &rt,int x){
// if(!rt && x==299181)while(1);
if(t[rt].val==x){
t[rt].cnt--;
t[rt].sz--;
if(!t[rt].cnt){
if(t[rt].l*t[rt].r==){rt=t[rt].l+t[rt].r;return;}
int p=t[rt].l;
while(t[p].r){st2[++top2]=p;p=t[p].r;}
if(top2){
t[st2[top2]].r=t[p].l;
pushup(st2[top2]);
t[p].l=t[rt].l;
t[p].r=t[rt].r;
while(top2)pushup(st2[top2--]);
}
else t[p].r=t[rt].r;
if(fafa){
if(t[fafa].l==rt) t[fafa].l=p;
else t[fafa].r=p;
}
pushup(p);
pushup(t[rt].l);
rt=p;
}
pushup(fafa);
return;
}
fafa=rt;
if(x<t[rt].val)Q_erase(t[rt].l,x);
else Q_erase(t[rt].r,x);
pushup(rt);
return;
}
int Q_rank(int rt,int x){
int res=;
while(rt){
if(t[rt].val<x){
res+=t[t[rt].l].sz+t[rt].cnt;
rt=t[rt].r;
}
else rt=t[rt].l;
}
return res+;
}
int Q_num(int rt,int k){
int res=;
while(rt){
if(t[t[rt].l].sz>=k){
res=t[rt].val;
rt=t[rt].l;
}
else if(t[t[rt].l].sz+t[rt].cnt>=k)return t[rt].val;
else k-=t[t[rt].l].sz+t[rt].cnt,rt=t[rt].r;
}
return res;
}
void Debug(int x){
if(!x)return;
printf("#%d: v:%d l:%d r:%d sz:%d cnt:%d\n",
x,t[x].val,t[x].l,t[x].r,t[x].sz,t[x].cnt);
Debug(t[x].l);Debug(t[x].r);
}
int n;
int main(){
// freopen("in.txt","r",stdin);
// freopen("out.out","w",stdout);
int i,j;
n=read();
int op,x;
int tct=;
while(n--){
op=read();x=read();
if(op!=)tct++;
switch(op){
case :{
flag=faf=;sz=;
insert(rot,x);
if(flag){
del(flag);
sort(vt+,vt+sz+);
if(flag==rot)Build(,sz,rot);
else Build(,sz,(t[faf].l==flag)?t[faf].l:t[faf].r);
}
break;
}
case :{fafa=;Q_erase(rot,x);break;}
case :{
int ans=Q_rank(rot,x);
printf("%d\n",ans);
break;
}
case :{
int ans=Q_num(rot,x);
printf("%d\n",ans);
break;
}
case :{
int res=pre(rot,x);
printf("%d\n",t[res].val);
break;
}
case :{
int res=sub(rot,x);
printf("%d\n",t[res].val);
break;
}
case :{
Debug(rot);
break;
}
}
}
return ;
}
Bzoj3224 / Tyvj 1728 普通替罪羊树的更多相关文章
- [BZOJ3224]Tyvj 1728 普通平衡树
[BZOJ3224]Tyvj 1728 普通平衡树 试题描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个) ...
- bzoj3224: Tyvj 1728 普通平衡树(平衡树)
bzoj3224: Tyvj 1728 普通平衡树(平衡树) 总结 a. cout<<(x=3)<<endl;这句话输出的值是3,那么对应的,在splay操作中,当父亲不为0的 ...
- 替罪羊树—BZOJ3224: Tyvj 1728 普通平衡树
冬令营被平衡树坑了之后,打算苦练一番数据结构(QAQ). 先是打了一下想学好久的替罪羊树. 替罪羊树实现方法很简单,就是在不满足平衡条件的时候暴力重构子树. 调试小结: 1.删除操作分两类情况:如果某 ...
- bzoj3224 Tyvj 1728 普通平衡树(名次树+处理相同)
3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 5354 Solved: 2196[Submit][Sta ...
- bzoj3224: Tyvj 1728 普通平衡树(splay)
3224: Tyvj 1728 普通平衡树 题目:传送门 题解: 啦啦啦啦又来敲个模版水经验啦~ 代码: #include<cstdio> #include<cstring> ...
- 【权值线段树】bzoj3224 Tyvj 1728 普通平衡树
一个板子. #include<cstdio> #include<algorithm> using namespace std; #define N 100001 struct ...
- BZOJ3224 Tyvj 1728 普通平衡树(Treap)
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...
- 【权值分块】bzoj3224 Tyvj 1728 普通平衡树
权值分块和权值线段树的思想一致,离散化之后可以代替平衡树的部分功能. 部分操作的时间复杂度: 插入 删除 全局排名 全局K大 前驱 后继 全局最值 按值域删除元素 O(1) O(1) O(sqrt(n ...
- 绝对是全网最好的Splay 入门详解——洛谷P3369&BZOJ3224: Tyvj 1728 普通平衡树 包教包会
平衡树是什么东西想必我就不用说太多了吧. 百度百科: 一个月之前的某天晚上,yuli巨佬为我们初步讲解了Splay,当时接触到了平衡树里的旋转等各种骚操作,感觉非常厉害.而第二天我调Splay的模板竟 ...
随机推荐
- JAVA mysql数据库 配置
mysql 版本 5.7 数据库连接版本 <!--MySql--><dependency> <groupId>mysql</groupId> <a ...
- iOS开发NSDate详解
1. 用于创建NSDate实例的类方法有 + (id)date; 返回当前时间 + (id)dateWithTimeIntervalSinceNow:(NSTimeInterval)secs; 返回以 ...
- 3DMAX2016破解教程
首先,断网. 然后,下载3DMAX2016注册机. 然后,打开已经安装的3DMAX2016,会出现下图,点击激活按钮. 之后,以管理员身份打开3DMAX2016注册机,把申请号复制到注册机里面的请求码 ...
- PAT L2-028 秀恩爱分得快
https://pintia.cn/problem-sets/994805046380707840/problems/994805054698012672 古人云:秀恩爱,分得快. 互联网上每天都有大 ...
- HDU 2117 Just a Numble
http://acm.hdu.edu.cn/showproblem.php?pid=2117 Problem Description Now give you two integers n m, yo ...
- vue-cli2使用cdn方式引入cytoscape
1. index.html头部引用 <script src="https://cdnjs.cloudflare.com/ajax/libs/cytoscape/3.2.19/cytos ...
- cacti安装spine 解决WARNING: Result from CMD not valid. Partial Result: U错误
安装spine用来替换cacti原本的执行方式,需要的包在附件中,请注意spine的安装包和你安装的cacti版本不用相同,最好是最新的spine 1.安装gcc #yum install -y gc ...
- checkBox1_CheckedChanged(object sender, EventArgs e)和checkBox1_CheckStateChanged(object sender, EventArgs e)不同
using System; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms ...
- 基于c++和opencv底层的图像旋转
图像旋转:本质上是对旋转后的图片中的每个像素计算在原图的位置. 在opencv包里有自带的旋转函数,当你知道倾斜角度theta时: 用getRotationMatrix2D可得2X3的旋转变换矩阵 M ...
- [转]matlab中squeeze函数的用法,numel的用法
squeeze的作用是移除单一维. 如果矩阵哪一个维数是1,B=squeeze(A)就将这个维数移除. 考虑2-by-1-by-3 数组Y = rand(2,1,3). 这个数组有单一维 —就是每页仅 ...