P3369 【模板】普通平衡树
纯板子。。。。
题意:
- 插入 xx 数
- 删除 xx 数(若有多个相同的数,因只删除一个)
- 查询 xx 数的排名(排名定义为比当前数小的数的个数 +1+1 。若有多个相同的数,因输出最小的排名)
- 查询排名为 xx 的数
- 求 xx 的前驱(前驱定义为小于 xx ,且最大的数)
- 求 xx 的后继(后继定义为大于 xx ,且最小的数)
然后。。。
然后就没有然后了。。。。
注意rotate。。。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cctype>
using namespace std;
#define olinr return
#define love_nmr 0
#define INF 0x7ffffffa
#define mod 123123
int n;
int cnt;
int root;
int siz[mod];
int dat[mod];
int fat[mod];
int num[mod];
int son[mod][];
inline int read()
{
int f=,x=;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')
f=-f;
ch=getchar();
}
while(isdigit(ch))
{
x=(x<<)+(x<<)+(ch^);
ch=getchar();
}
olinr x*f;
}
inline void put(int x)
{
if(x<)
{
putchar('-');
x=-x;
}
if(x>)
put(x/);
putchar(x%+'');
} /* ------------------------olinr love nmr--------------------------------*/ inline void update(int x)
{
siz[x]=siz[son[x][]]+siz[son[x][]]+num[x];
}
inline void rotate(int x,int &o)
{
int y=fat[x];
int z=fat[y];
bool xx=son[y][]==x;
bool yy=xx^;
if(y==o)
o=x;
else
son[z][son[z][]==y]=x;
fat[x]=z;
fat[y]=x;
fat[son[x][yy]]=y;
son[y][xx]=son[x][yy];
son[x][yy]=y;
update(y);
update(x);
olinr;
}
inline void splay(int x,int &o)
{
while(x!=o)
{
int y=fat[x];
int z=fat[y];
if(y!=o)
{
if((son[y][]==x)^(son[z][]==y))
rotate(x,o);
else
rotate(y,o);
}
rotate(x,o);
}
}
inline int x_rank_n(int x)
{
int now=root;
int rank=;
while(+love_nmr)
{
if(x<dat[now])
now=son[now][];
else
{
rank+=siz[son[now][]];
if(x==dat[now])
{
splay(now,root);
olinr rank+;
}
rank+=num[now];
now=son[now][];
}
}
}
inline int n_rank_x(int x)
{
int now=root;
while(+love_nmr)
{
if(siz[son[now][]]>=x)
now=son[now][];
else
{
if(num[now]+siz[son[now][]]>=x)
olinr dat[now];
x-=(num[now]+siz[son[now][]]);
now=son[now][];
}
}
}
inline int pre(int x)
{
x_rank_n(x);
int now=son[root][];
while(son[now][])
now=son[now][];
olinr now;
}
inline int nxt(int x)
{
x_rank_n(x);
int now=son[root][];
while(son[now][])
now=son[now][];
olinr now;
}
inline int del(int x)
{
int l=pre(x);
int r=nxt(x);
splay(l,root);
splay(r,son[root][]);
int now=son[son[root][]][];
siz[now]--;
num[now]--;
if(!num[now])
{
son[fat[now]][]=;
fat[now]=;
}
splay(son[root][],root);
}
inline void insert(int x)
{
if(!root)
{
root=++cnt;
siz[root]=;
dat[root]=x;
num[root]=;
olinr;
}
int fa=;
int now=root;
while(+love_nmr)
{
if(dat[now]==x)
{
num[now]++;
siz[now]++;
splay(now,root);
olinr;
}
fa=now;
now=son[now][x>dat[now]];
if(!now)
{
now=++cnt;
fat[now]=fa;
son[fa][x>dat[fa]]=now;
num[now]++;
siz[now]++;
dat[now]=x;
splay(now,root);
olinr;
}
}
}
int main()
{
n=read();
int flag,x;
insert(INF);
insert(-INF);
for(int i=;i<=n;i++)
{
flag=read();
x=read();
if(flag==) insert(x);
if(flag==) del(x);
if(flag==){put(x_rank_n(x)-);putchar('\n');}
if(flag==){put(n_rank_x(x+));putchar('\n');}
if(flag==){insert(x);put(dat[pre(x)]);putchar('\n');del(x);}
if(flag==){insert(x);put(dat[nxt(x)]);putchar('\n');del(x);}
}
olinr love_nmr;
}
注释QAQ
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cctype>
using namespace std;
#define R register
#define IL inline
#define INF 2147483640
#define mod 125125
#define II int
II root; //根的编号
II n; //n个操作
II cnt; //编号
II fa[mod]; //fa[i]代表i的父亲
II son[mod][]; //son[i][0]代表i的左儿子,son[i][1]代表i的右儿子
II data[mod]; //data[i]代表树上编号为i的点的值
II size[mod]; //size[i]表示以i为根的子树的sum的和 (大小) (包括自己)
II sum[mod]; //sum[i]表示数字i的个数
IL II read() //快读(有负数)
{
R II x=,f=;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')
f=-f;
ch=getchar();
}
while(isdigit(ch))
{
x=(x<<)+(x<<)+(ch^);
ch=getchar();
}
return x*f;
}
IL void update(R II x) //更新x
{
size[x]=size[son[x][]]+size[son[x][]]+sum[x];
//当前点的size == 左儿子的size + 右儿子的size + 当前点的个数
}
IL void rotate(R II x,R II &o) //旋转
{
R II y=fa[x]; //y为x的父亲
R II z=fa[y]; //z为y的父亲,z为x的爷爷
R bool xx=(son[y][]==x); //xx表示y的右儿子是否为x
R bool yy=xx^; //yy表示y的左儿子是否为x
if(y==o) //x的父亲y是旋转的目标点
o=x; //目标点变为x
else //x的父亲y不是旋转的目标点
son[z][son [z][]==y]=x; //如果z的右儿子是y,那么现在z的右儿子是x;如果z的右儿子不是y,那么现在z的左儿子是x
fa[x]=z; //x的父亲是z
fa[y]=x; //y的父亲是x(x转了上去)
fa[son[x][yy]]=y; //如果原来y的左儿子是x,那么现在x的右儿子是y;如果原来y的右儿子是x,那么现在x的左儿子是y
son[y][xx]=son[x][yy]; //原来x的(右||左)儿子变成了先在y的(左||右)儿子
son[x][yy]=y; //如果原来y的(左||右)儿子是x,那么现在x的(右||左)儿子是y
update(y); //维护y
update(x); //维护x
}
IL void splay(R II x,R II &o)
{
while(x!=o) //只要为转到目标节点
{
R II y=fa[x]; //y是x的父亲
R II z=fa[y]; //z是y的父亲,x的爷爷
if(y!=o) //如果y不是目标节点
{
if((son[y][]==x)^(son[z][]==y)) //如果xyz不在一条直链上
rotate(x,o); //x朝o的方向转
else //在一条直链上
rotate(y,o); //转y
}
rotate(x,o); //转x
}
}
IL void insert(R II x)
{
if(!root) //是根
{ //初始化
root=++cnt;
data[root]=x;
size[root]=;
sum[root]=;
return;
}
R II now=root; //从根开始找合适位置
R II fat=; //now的father
while()
{
if(data[now]==x) //树中已有该元素
{
sum[now]++; //累计数量
splay(now,root); //转
return;
}
fat=now;
now=son[now][data[now]<x]; //now往孩子上跳
if(!now) //跳到了叶子的孩子(还没有)
{
now=++cnt; //初始化
fa[now]=fat;
son[fat][data[fat]<x]=now;
size[now]++;
sum[now]++;
data[now]=x;
splay(now,root);
return;
}
}
}
IL II x_rank_n(R II x) //找树中的数x的排名
{
R II rank=;
R II now=root; //从根往下找
while()
{
if(x<data[now]) //小于当前点往左跳
now=son[now][];
else
{
rank+=size[son[now][]];//排名加上左子树大小(x一定比左子树所有值都大,不然就会往左跳)
if(x==data[now]) //找到了x
{
splay(now,root); //转上去
return rank+; //x的位置
}
rank+=sum[now]; //往右跳说明它比前面所有数都大,所以要累计前面数的个数
now=son[now][]; //累计完后在往后跳
}
}
}
IL II rank_n_x(R II x)
{
R II rank=;
R II now=root;
while()
{
if(size[son[now][]]>=x) //目标在左子树
now=son[now][]; //往左跳
else
{
if(sum[now]+size[son[now][]]>=x) //now就是x的位置
return data[now];
x-=(sum[now]+size[son[now][]]); //x减左边个数
now=son[now][]; //再向右跳
}
}
}
IL II pre(R II x)
{
x_rank_n(x);
R II now=son[root][];
while(son[now][])
now=son[now][];
return now;
}
IL II nxt(R II x)
{
x_rank_n(x);
R II now=son[root][];
while(son[now][])
now=son[now][];
return now;
}
IL void del(R II x)
{
R II l=pre(x);
R II r=nxt(x);
splay(l,root);
splay(r,son[root][]);
R II now=son[son[root][]][];
sum[now]--;
size[now]--;
if(!sum[now])
{
son[fa[now]][]=;
fa[now]=;
}
splay(son[root][],root);
}
int main()
{
ios::sync_with_stdio(false);
n=read();
insert(-INF);
insert(INF);
for(R II i=;i<=n;i++)
{
R II x=read();
R II y=read();
if(x==) insert(y);
if(x==) del(y);
if(x==) printf("%d\n",x_rank_n(y)-);
if(x==) printf("%d\n",rank_n_x(y+));
if(x==) insert(y),printf("%d\n",data[pre(y)]),del(y);
if(x==) insert(y),printf("%d\n",data[nxt(y)]),del(y);
}
return ;
}
P3369 【模板】普通平衡树的更多相关文章
- luoguP3391[模板]文艺平衡树(Splay) 题解
链接一下题目:luoguP3391[模板]文艺平衡树(Splay) 平衡树解析 这里的Splay维护的显然不再是权值排序 现在按照的是序列中的编号排序(不过在这道题目里面就是权值诶...) 那么,继续 ...
- luoguP3369[模板]普通平衡树(Treap/SBT) 题解
链接一下题目:luoguP3369[模板]普通平衡树(Treap/SBT) 平衡树解析 #include<iostream> #include<cstdlib> #includ ...
- 【洛谷P3369】 (模板)普通平衡树
https://www.luogu.org/problemnew/show/P3369 Splay模板 #include<iostream> #include<cstdio> ...
- [luogu3369/bzoj3224]普通平衡树(splay模板、平衡树初探)
解题关键:splay模板题整理. 如何不加入极大极小值?(待思考) #include<cstdio> #include<cstring> #include<algorit ...
- 【模板】平衡树——Treap和Splay
二叉搜索树($BST$):一棵带权二叉树,满足左子树的权值均小于根节点的权值,右子树的权值均大于根节点的权值.且左右子树也分别是二叉搜索树.(如下) $BST$的作用:维护一个有序数列,支持插入$x$ ...
- 【洛谷P3369】普通平衡树——Splay学习笔记(一)
二叉搜索树(二叉排序树) 概念:一棵树,若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值: 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值: 它的左.右子树也分别为二叉搜索树 ...
- 洛谷.3369.[模板]普通平衡树(Splay)
题目链接 第一次写(2017.11.7): #include<cstdio> #include<cctype> using namespace std; const int N ...
- 洛谷.3369.[模板]普通平衡树(fhq Treap)
题目链接 第一次(2017.12.24): #include<cstdio> #include<cctype> #include<algorithm> //#def ...
- 洛谷.3391.[模板]文艺平衡树(Splay)
题目链接 //注意建树 #include<cstdio> #include<algorithm> const int N=1e5+5; //using std::swap; i ...
- 文艺平衡Splay树学习笔记(2)
本blog会讲一些简单的Splay的应用,包括但不局限于 1. Splay 维护数组下标,支持区间reserve操作,解决区间问题 2. Splay 的启发式合并(按元素多少合并) 3. 线段树+Sp ...
随机推荐
- Java--异常与字符串
1.处理异常 try-catch以及try-catch-finally try{ //一些会抛出的异常 }catch(Exception e){ //处理该异常的代码块 }catch(Exceptio ...
- 一个类的类类型是Class类的实例,即类的字节码
new 是静态加载类,编译时期加载.一遍功能性的类 需要动态加载
- 如何查看myeclipse是否激活
myEclipse---->Subscription information--->Subscription expiration date 看这个日期到什么时候!另外建议别用太高版本的M ...
- 机器学习 Generative Learning Algorithm (A)
引言 前面几讲,我们主要探讨了如何对 p(y|x;θ) (即y 相对于x的条件概率)进行建模的几种学习算法,比如,logistic regression 对 p(y|x;θ) 进行建模的假设函数为 h ...
- netsh wlan start hostednetwork
常用的无线网命令: 一.开启系统承载网络模块和新建无线网络命令: netsh wlan set hostednetwork mode=allow ssid=wifi key=12345678说明:ss ...
- uoj problem 21 缩进优化
题目: 小O是一个热爱短代码的选手.在缩代码方面,他是一位身经百战的老手.世界各地的OJ上,很多题的最短解答排行榜都有他的身影.这令他感到十分愉悦. 最近,他突然发现,很多时候自己的程序明明看起来比别 ...
- linux绑定多个ip(转载)
在Linux下有时候需要给一个网卡绑定多个IP,本文介绍在Redhat系列(redhat,Fedora Core,Centos)中的实现方法和一种在Gentoo等其他Linux中普遍适用的方法. 1. ...
- YARN指令
如果是使用了Cloudera来安装到此路径下: /opt/cloudera/parcels/CDH-5.10.2-1.cdh5.10.2.p0.5/bin 执行: sudo ./yarn applic ...
- 全文检索技术---solr
1 Solr介绍 1.1 什么是solr Solr 是Apache下的一个顶级开源项目,采用Java开发,它是基于Lucene的全文搜索服务器.Solr可以独立运行在Jetty.Tom ...
- 6.7 安装ant
准备好安装包: 安装vim: 解压: tar -xzvf apahce-ant-1.10.1-bin.tar.gz 这里,我将apache-ant-1.10.1-bin.tar.gz复制并解压到了/h ...