BZOJ3224:普通平衡树——题解
http://www.lydsy.com/JudgeOnline/problem.php?id=3224
题面源于洛谷
题目描述
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
插入x数
删除x数(若有多个相同的数,因只删除一个)
查询x数的排名(排名定义为比当前数小的数的个数+1。若有多个相同的数,因输出最小的排名)
查询排名为x的数
求x的前驱(前驱定义为小于x,且最大的数)
- 求x的后继(后继定义为大于x,且最小的数)
输入输出格式
输入格式:
第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号( 1 \leq opt \leq 61≤opt≤6 )
输出格式:
对于操作3,4,5,6每行输出一个数,表示对应答案
输入输出样例
10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
106465
84185
492737
——————————————————————————————
http://blog.csdn.net/clove_unique/article/details/50630280
所以最开始学习splay就从上面的博客学的话做这道题就是切。
简单讲几个问题吧。
1.findx操作。
和我前面博客的kthmin(或者query)思路一致,就是变成了非递归的。
2.find操作。
从根出发,判断当前左右子结点的值和x比较就可以知道要往哪里走了。
同时沿途中顺便记录排名即可,方法同findx操作。
3.del操作。
如果看过我前面的博客的话就会发现del操作只能删除根节点。
那么我们怎么删除任意结点呢?很简单,和find函数联动即可。
因为find(x)函数会返回x的排名,但同时会把x放在根上,所以又转换成了删除根节点的问题了。
#include<cstdio>
#include<queue>
#include<cctype>
#include<cstring>
#include<cmath>
#include<vector>
#include<algorithm>
using namespace std;
const int N=;
inline int read(){
int X=,w=;char ch=;
while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
while(isdigit(ch))X=(X<<)+(X<<)+(ch^),ch=getchar();
return w?-X:X;
}
int fa[N],tr[N][],key[N],cnt[N],size[N];
int root,sz;
inline void clear(int x){
fa[x]=tr[x][]=tr[x][]=key[x]=cnt[x]=size[x]=;
return;
}
inline bool get(int x){
return tr[fa[x]][]==x;
}
inline void update(int x){
if(x){
size[x]=cnt[x];
if(tr[x][])size[x]+=size[tr[x][]];
if(tr[x][])size[x]+=size[tr[x][]];
}
return;
}
inline void rotate(int x){
int old=fa[x],oldf=fa[old],which=get(x);
tr[old][which]=tr[x][which^];fa[tr[old][which]]=old;
fa[old]=x;tr[x][which^]=old;fa[x]=oldf;
if(oldf)tr[oldf][tr[oldf][]==old]=x;
update(old);update(x);
return;
}
inline void splay(int x){
int f=fa[x];
while(f){
if(fa[f])rotate((get(x)==get(f)?f:x));
rotate(x);f=fa[x];
}
root=x;
return;
}
inline void insert(int v){
if(!root){
sz++;tr[sz][]=tr[sz][]=fa[sz]=;
key[sz]=v;cnt[sz]=size[sz]=;root=sz;
return;
}
int now=root,f=;
while(){
if(key[now]==v){
cnt[now]++;update(now);update(f);splay(now);
break;
}
f=now;
now=tr[now][key[now]<v];
if(!now){
sz++;tr[sz][]=tr[sz][]=;fa[sz]=f;
key[sz]=v;cnt[sz]=size[sz]=;
tr[f][key[f]<v]=sz;
update(f);splay(sz);
break;
}
}
return;
}
inline int find(int v){//查询v的排名
int ans=,now=root;
while(){
if(v<key[now])now=tr[now][];
else{
ans+=(tr[now][]?size[tr[now][]]:);
if(v==key[now]){
splay(now);
return ans+;
}
ans+=cnt[now];
now=tr[now][];
}
}
}
inline int findx(int x){//找到排名为x的点
int now=root;
while(){
if(tr[now][]&&x<=size[tr[now][]])now=tr[now][];
else{
int temp=(tr[now][]?size[tr[now][]]:)+cnt[now];
if(x<=temp)return key[now];
x-=temp;now=tr[now][];
}
}
}
inline int pre(){//前驱
int now=tr[root][];
while(tr[now][])now=tr[now][];
return now;
}
inline int nxt(){//后继
int now=tr[root][];
while(tr[now][])now=tr[now][];
return now;
}
inline void del(int x){
find(x);
if(cnt[root]>){
cnt[root]--;return;
}
if(!tr[root][]&&!tr[root][]){
clear(root);root=;return;
}
if(!tr[root][]){
int oldroot=root;root=tr[root][];fa[root]=;clear(oldroot);return;
}
else if(!tr[root][]){
int oldroot=root;root=tr[root][];fa[root]=;clear(oldroot);return;
}
int leftbig=pre(),oldroot=root;
splay(leftbig);
fa[tr[oldroot][]]=root;
tr[root][]=tr[oldroot][];
clear(oldroot);
update(root);
return;
}
int main(){
int n=read();
for(int i=;i<=n;i++){
int opt=read();
int k=read();
if(opt==)insert(k);
if(opt==)del(k);
if(opt==)printf("%d\n",find(k));
if(opt==)printf("%d\n",findx(k));
if(opt==){
insert(k);
printf("%d\n",key[pre()]);
del(k);
}
if(opt==){
insert(k);
printf("%d\n",key[nxt()]);
del(k);
}
}
return ;
}
UPD :Treap
#include<cmath>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int INF=;
const int N=1e5+;
inline int read(){
int X=,w=;char ch=;
while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
while(isdigit(ch))X=(X<<)+(X<<)+(ch^),ch=getchar();
return w?-X:X;
}
struct treap{
int l,r,p,size,cnt,key;
#define lc(x) tr[x].l
#define rc(x) tr[x].r
#define v(x) tr[x].key
#define p(x) tr[x].p
#define c(x) tr[x].cnt
#define s(x) tr[x].size
}tr[N];
int sz,rt;
inline int rand(){
static int seed=;
return seed=(ll)seed*%;
}
inline void upt(int k){
s(k)=s(lc(k))+s(rc(k))+c(k);
}
inline void zig(int &k){
int y=lc(k);lc(k)=rc(y);rc(y)=k;
s(y)=s(k);upt(k);
k=y;
}
inline void zag(int &k){
int y=rc(k);rc(k)=lc(y);lc(y)=k;
s(y)=s(k);upt(k);
k=y;
}
inline void insert(int &k,int v){
if(!k){
k=++sz;v(k)=v;p(k)=rand();
c(k)=s(k)=;lc(k)=rc(k)=;
return;
}
else s(k)++;
if(v(k)==v)c(k)++;
else if(v<v(k)){
insert(lc(k),v);
if(p(lc(k))<p(k))zig(k);
}else{
insert(rc(k),v);
if(p(rc(k))<p(k))zag(k);
}
}
inline void del(int &k,int v){
if(v(k)==v){
if(c(k)>)c(k)--,s(k)--;
else if(!lc(k) || !rc(k))k=lc(k)+rc(k);
else if(p(lc(k))<p(rc(k)))zig(k),del(k,v);
else zag(k),del(k,v);
return;
}
else s(k)--;
if(v<v(k))del(lc(k),v);
else del(rc(k),v);
}
inline int find(int v){
int x=rt,res=;
while(x){
if(v==v(x))return res+s(lc(x))+;
if(v<v(x))x=lc(x);
else res+=s(lc(x))+c(x),x=rc(x);
}
return res;
}
inline int findx(int k){
int x=rt;
while(x){
if(s(lc(x))<k&&s(lc(x))+c(x)>=k)return v(x);
if(s(lc(x))>=k)x=lc(x);
else k-=s(lc(x))+c(x),x=rc(x);
}
return ;
}
inline int pre(int v){
int x=rt,res=-INF;
while(x){
if(v(x)<v)res=v(x),x=rc(x);
else x=lc(x);
}
return res;
}
inline int nxt(int v){
int x=rt,res=INF;
while(x){
if(v(x)>v)res=v(x),x=lc(x);
else x=rc(x);
}
return res;
}
int main(){
int n=read();
for(int i=;i<=n;i++){
int opt=read();
int k=read();
if(opt==)insert(rt,k);
if(opt==)del(rt,k);
if(opt==)printf("%d\n",find(k));
if(opt==)printf("%d\n",findx(k));
if(opt==){
insert(rt,k);
printf("%d\n",pre(k));
del(rt,k);
}
if(opt==){
insert(rt,k);
printf("%d\n",nxt(k));
del(rt,k);
}
}
return ;
}
BZOJ3224:普通平衡树——题解的更多相关文章
- 【洛谷P3369】【模板】普通平衡树题解
[洛谷P3369][模板]普通平衡树题解 题目链接 题意: 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3 ...
- [转载]无旋treap:从好奇到入门(例题:bzoj3224 普通平衡树)
转载自ZZH大佬,原文:http://www.cnblogs.com/LadyLex/p/7182491.html 今天我们来学习一种新的数据结构:无旋treap.它和splay一样支持区间操作,和t ...
- [您有新的未分配科技点]无旋treap:从好奇到入门(例题:bzoj3224 普通平衡树)
今天我们来学习一种新的数据结构:无旋treap.它和splay一样支持区间操作,和treap一样简单易懂,同时还支持可持久化. 无旋treap的节点定义和treap一样,都要同时满足树性质和堆性质,我 ...
- [BZOJ3224]普通平衡树(旋转treap,STL-vector)
3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 20328 Solved: 8979[Submit][St ...
- [bzoj3224]普通平衡树/3223文艺平衡树
这是一道很普通的题.. 最近花了很多时间来想要去干什么,感觉自己还是太拿衣服 做这道题是因为偶尔看到了lavender的blog和她的bzoj早期AC记录,就被题目深深地吸引到了,原因有二: 自己sp ...
- BZOJ3224普通平衡树【Splay】
3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 11751 Solved: 5013 Descriptio ...
- [TYVJ1728/BZOJ3224]普通平衡树-替罪羊树
Problem 普通平衡树 Solution 本题是裸的二叉平衡树.有很多种方法可以实现.这里打的是替罪羊树模板. 此题极其恶心. 前驱后继模块需要利用到rank模块来换一种思路求. 很多细节的地方容 ...
- bzoj3224 普通平衡树(c++vector)
Tyvj 1728 普通平衡树 2014年8月23日6,4365 Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有 ...
- BZOJ3224普通平衡树——非旋转treap
题目: 此为平衡树系列第一道:普通平衡树您需要写一种数据结构,来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数, ...
随机推荐
- 「日常训练&知识学习」莫队算法(二):树上莫队(Count on a tree II,SPOJ COT2)
题意与分析 题意是这样的,给定一颗节点有权值的树,然后给若干个询问,每次询问让你找出一条链上有多少个不同权值. 写这题之前要参看我的三个blog:Codeforces Round #326 Div. ...
- Qt PC 安卓 tcp传输文件
废话不多说,如题,上代码 qt PC端 头文件 //网络部分 #include <QTcpSocket> #include <QFile> #include <QFile ...
- 那些年我们不爱学的mysql单词
MySQL 一种关系型数据库 database 数据库,简称DB databases 数据库的复数,代表多个数据库 net 网络/服务 start 启动 stop 停止 root MySQL数据库中的 ...
- 【cookie接口】- jmeter - (请求提示no cookie)
1.虽然 请求成功 响应码 200 ,但是 返回code 1 ,表示接口不成功 2.加入 空的cookie 管理器就可以了 返回 code 0 注意:状态码 200 只是表示请求是成功的 , ...
- 数据库Mysql的学习(一)-启动和进入
数据库:按照数据结构来组织储存和管理数据的仓库. Mysql是关系型数据库管理系统 Mysql安装好之后... mysql的启动 1:通过控制面板里的”服务“找到mysql右键启动即可 2:开始菜单搜 ...
- 日历(Calendar)模块
#usr/bin/python3 #! -*-conding : utf-8 -*- #2018.3.14 """ 日历(Calendar)模块 此模块的函数都是日历相关 ...
- 【转载】JAVA常见面试题及解答(精华)
JAVA常见面试题及解答(精华) 1)transient和volatile是java关键字吗?(瞬联) 如果用transient声明一个实例变量,当对象存储时,它的值不需要维持.例如: ...
- Hadoop源码解析 1 --- Hadoop工程包架构解析
1 Hadoop中各工程包依赖简述 Google的核心竞争技术是它的计算平台.Google的大牛们用了下面5篇文章,介绍了它们的计算设施. GoogleCluster: http:// ...
- 【转】jQuery最佳实践
上周,我整理了<jQuery设计思想>. 那篇文章是一篇入门教程,从设计思想的角度,讲解"怎么使用jQuery".今天的文章则是更进一步,讲解"如何用好jQu ...
- JavaScript中的事件代理/委托
事件委托在JS高级程序设计中的定义为"利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件" 如何理解上面的这句话呢,在网上,大牛们一般都使用收快递这个例子来解释的, ...