维护区间添加,删除,前驱,后继,排名,逆排名 普通平衡树

#include <cstdio>
#define ls t[now].ch[0]
#define rs t[now].ch[1]
int min(int x,int y){return x<y?x:y;}
int max(int x,int y){return x>y?x:y;}
const int inf=0x3f3f3f3f;
const int N=100010;
struct Splay
{
int par,ch[2],dat,siz,cnt;
}t[N];
int tot=0,root,t_size=0;
int identity(int x)//是父亲的左0/右1孩子
{
return t[t[x].par].ch[0]==x?0:1;
}
void connect(int fa,int s,int typ)//建立父子关系
{
t[fa].ch[typ]=s;
t[s].par=fa;
}
void updata(int now)
{
t[now].siz=t[ls].siz+t[rs].siz+t[now].cnt;
}
void rotate(int p,int typ)//0左上旋,1右上旋
{
int q=t[p].ch[typ];//要转的儿子
connect(p,t[q].ch[typ^1],typ);//顺序不能换,得注意一下
connect(t[p].par,q,identity(p));
connect(q,p,typ^1);
updata(p),updata(q);//顺序不能换
}
void splay(int v,int u)//把v位置调整至u
{
u=t[u].par;
while(t[v].par!=u)
{
int f=t[v].par,g=t[f].par;
if(g==u||identity(v)!=identity(f))
rotate(f,identity(v));
else
{
rotate(g,identity(f));
rotate(f,identity(v));
}
}
}
int New(int dat,int fa)
{
t[++tot].par=fa,t[tot].dat=dat,t[tot].cnt=1,t[tot].siz=1,t_size++;
return tot;
}
void free(int x)
{
t[x].siz=0,t[x].dat=0,t[x].cnt=0,t[x].par=0,t[x].ch[0]=0,t[x].ch[1]=0;
if(x==tot) tot--;
}
void insert(int dat)
{
if(!t_size) {root=New(dat,0);connect(0,tot,1);return;}//特判建虚根
int now=root,las;
while(1)
{
int tpy=t[now].dat>dat?0:1;
t[now].siz++;
las=now;
now=t[now].ch[tpy];
if(!now)
{
now=New(dat,las);
t[las].ch[tpy]=now;
break;
}
if(t[now].dat==dat)
{
t[now].cnt++;
break;
}
}
splay(now,root);
root=now;
}
int find(int dat)//查找并调整
{
int now=root;
while(1)
{
if(t[now].dat==dat)
{
splay(now,root);//调整位置至根
root=now;
return now;
}
int typ=t[now].dat>dat?0:1;
now=t[now].ch[typ];
}
}
int g_max(int now)
{
return t[now].ch[1]?g_max(t[now].ch[1]):now;
}
void extrack(int dat)
{
int loc=find(dat);//找到删除节点位置并伸展
if(t[loc].cnt>1) {t[loc].cnt--;t[loc].siz--;return;}//删除一个值并更新
t_size--;//整棵树的大小--
if(!t[root].ch[0]) {root=t[root].ch[1];return;}//左子树空拿右子树顶
loc=g_max(t[root].ch[0]);//找到左子树最大值的位置
splay(loc,t[root].ch[0]);//把左子树最大值伸展至根节点
connect(t[root].ch[0],t[root].ch[1],1);//建立联系
loc=root;//记录一下原根以便free
root=t[root].ch[0];//更新根节点
connect(0,root,1);//与虚根建立关系
updata(root);//更新大小
free(loc);//释放原根
}
void get_rank(int x)//查询x的排名
{
root=find(x);
printf("%d\n",t[t[root].ch[0]].siz+1);
}
void fget_rank(int x)//排名为x的数
{
int now=root;
while(1)
{
if(t[ls].siz<x&&x<=t[ls].siz+t[now].cnt) {printf("%d\n",t[now].dat);return;}
else if(x>t[ls].siz+t[now].cnt) {x-=t[ls].siz+t[now].cnt;now=rs;}
else now=ls;
}
}
void get_pre(int x)
{
int m_max=-inf,now=root;
while(now)
{
if(t[now].dat<x) {m_max=max(m_max,t[now].dat);now=rs;}
else now=ls;
}
printf("%d\n",m_max);
}
void get_suc(int x)
{
int m_min=inf,now=root;
while(now)
{
if(t[now].dat>x) {m_min=min(m_min,t[now].dat);now=ls;}
else now=rs;
}
printf("%d\n",m_min);
}
int main()
{
int opt,x,n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&opt,&x);
if(opt==1)
insert(x);
else if(opt==2)
extrack(x);
else if(opt==3)
get_rank(x);//查询x的排名
else if(opt==4)
fget_rank(x);//查询排名为x的数
else if(opt==5)
get_pre(x);
else
get_suc(x);
}
return 0;
}

以上为2018.6.12版本


#include <cstdio>
#define ls t[now].ch[0]
#define rs t[now].ch[1]
#define f t[now].par
const int N=100010;
const int inf=0x3f3f3f3f;
int min(int x,int y){return x<y?x:y;}
int max(int x,int y){return x>y?x:y;}
struct Splay
{
int ch[2],par,siz,cnt,dat;
}t[N];
int root,wh_siz=0,tot=0;
int identity(int now)
{
return t[f].ch[1]==now;
}
void connect(int fa,int now,int typ)
{
t[now].par=fa;
t[fa].ch[typ]=now;
}
void updata(int now)
{
t[now].siz=t[ls].siz+t[rs].siz+t[now].cnt;
}
void rotate(int now)//把now旋转给它父亲
{
int typ=identity(now),p=f;
connect(p,t[now].ch[typ^1],typ);
connect(t[p].par,now,identity(p));
connect(now,p,typ^1);
updata(p),updata(now);
}
void splay(int now,int to)
{
to=t[to].par;
for(;f!=to;rotate(now))
if(t[f].par!=to)
rotate(identity(now)==identity(f)?f:now);
if(!to) root=now;
}
int New(int dat)
{
t[++tot].dat=dat;t[tot].cnt=1;t[tot].siz=1,wh_siz++;
return tot;
}
void free(int now)
{
t[now].dat=0,t[now].siz=0,t[now].par=0,t[now].cnt=0,ls=0,rs=0,wh_siz--;
if(tot==now) tot--;
}
void insert(int dat)
{
if(!wh_siz) {connect(0,root=New(dat),1);return;}
int now=root,las;
while(2333)
{
if(t[now].dat==dat) {t[now].siz++;t[now].cnt++;break;}
int tpy=t[now].dat<dat;
t[now].siz++;
las=now;now=t[now].ch[tpy];
if(!now) {connect(las,now=New(dat),tpy);break;}
}
splay(now,root);
}
int find(int dat)
{
int now=root;
for(int tpy;t[now].dat!=dat;now=t[now].ch[tpy])
tpy=t[now].dat<dat;
splay(now,root);
return now;
}
int g_max(int now)
{
return rs?g_max(rs):now;
}
void extrack(int dat)
{
int now=find(dat);
if(t[now].cnt>1) {t[now].cnt--;return;}
if(!ls) {root=rs;connect(0,root,1);free(now);return;}
int rt=g_max(ls);//新根
splay(rt,ls);
root=rt;
connect(rt,rs,1);
connect(0,rt,1);
free(now);
}
void pre(int dat)
{
int now=root,m_max=-inf;
for(int typ;now;now=t[now].ch[typ])
typ=t[now].dat<dat?m_max=max(m_max,t[now].dat),1:0;
printf("%d\n",m_max);
}
void suc(int dat)
{
int now=root,m_min=inf;
for(int typ;now;now=t[now].ch[typ])
typ=t[now].dat>dat?m_min=min(m_min,t[now].dat),0:1;
printf("%d\n",m_min);
}
void rank(int x)//查询排名为x的数
{
int now=root;
while(2333)
{
if(x<=t[ls].siz) now=ls;
else if(x>t[ls].siz+t[now].cnt) x-=t[ls].siz+t[now].cnt,now=rs;
else {printf("%d\n",t[now].dat);return;}
}
}
void frank(int dat)//查询dat的排名
{
int now=find(dat);
printf("%d\n",t[ls].siz+1);
}
int main()
{
int n,x,opt;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&opt,&x);
if(opt==1) insert(x);
else if(opt==2) extrack(x);
else if(opt==3) frank(x);
else if(opt==4) rank(x);
else if(opt==5) pre(x);
else suc(x);
}
return 0;
}

以上为2018.6.13版本


维护区间翻转:文艺平衡树

#include <cstdio>
#include <iostream>
#define ls t[now].ch[0]
#define rs t[now].ch[1]
#define f t[now].par
#define s t[now].ch[typ]
const int N=100010;
int root,n,m;
struct Splay
{
int c,ch[2],par,siz,tag;
}t[N];
int identity(int now)
{
return t[f].ch[1]==now;
}
void connect(int fa,int now,int typ)
{
f=fa;
t[f].ch[typ]=now;
}
void updata(int now)
{
t[now].siz=t[ls].siz+t[rs].siz+1;
}
void push_down(int now)
{
if(now&&t[now].tag)
{
t[ls].tag^=1;
t[rs].tag^=1;
t[now].tag=0;
std::swap(ls,rs);
}
}
void rotate(int now)
{
push_down(f),push_down(now);
int p=f,typ=identity(now);
connect(p,t[now].ch[typ^1],typ);
connect(t[p].par,now,identity(p));
connect(now,p,typ^1);
updata(p),updata(now);
}
void splay(int now,int to)
{
to=t[to].par;
for(int typ;f!=to;rotate(now))
if(t[f].par!=to)
rotate(identity(now)==identity(f)?f:now);
if(!to) root=now;
}
int build(int l,int r,int fa)
{
if(l>r) return 0;
int now=l+r>>1;
t[now].c=now-1;
t[now].par=fa;
updata(now);
if(l==r) return now;
ls=build(l,now-1,now);
rs=build(now+1,r,now);
updata(now);
return now;
}
int find(int siz)
{
int now=root;
for(int typ;;now=s)
{
push_down(now);
if(t[ls].siz>=siz) typ=0;
else if(t[ls].siz+1<siz) siz-=t[ls].siz+1,typ=1;
else return now;
}
}
void turn(int l,int r)
{
int L=find(l-1),R=find(r+1);
splay(R,root);
splay(L,t[root].ch[0]);
t[t[L].ch[1]].tag^=1;
}
void write(int now)
{
if(!now) return;
push_down(now);
write(ls);
if(t[now].c!=0&&t[now].c!=n+1)
printf("%d ",t[now].c);
write(rs);
}
int main()
{
int l,r;
scanf("%d%d",&n,&m);
connect(0,root=build(1,n+2,0),1);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&l,&r);
turn(l+1,r+1);
//write(root);
}
write(root);
return 0;
}

2018.6.14

平衡树Splay的更多相关文章

  1. hiho #1329 : 平衡树·Splay

    #1329 : 平衡树·Splay 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Ho:小Hi,上一次你跟我讲了Treap,我也实现了.但是我遇到了一个关键的问题. ...

  2. 【BZOJ3224】Tyvj 1728 普通平衡树 Splay

    Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数 ...

  3. BZOJ3224/洛谷P3391 - 普通平衡树(Splay)

    BZOJ链接 洛谷链接 题意简述 模板题啦~ 代码 //普通平衡树(Splay) #include <cstdio> int const N=1e5+10; int rt,ndCnt; i ...

  4. Hihocoder 1329 平衡树·Splay(平衡树)

    Hihocoder 1329 平衡树·Splay(平衡树) Description 小Ho:小Hi,上一次你跟我讲了Treap,我也实现了.但是我遇到了一个关键的问题. 小Hi:怎么了? 小Ho:小H ...

  5. 【阶梯报告】洛谷P3391【模板】文艺平衡树 splay

    [阶梯报告]洛谷P3391[模板]文艺平衡树 splay 题目链接在这里[链接](https://www.luogu.org/problemnew/show/P3391)最近在学习splay,终于做对 ...

  6. luoguP3391[模板]文艺平衡树(Splay) 题解

    链接一下题目:luoguP3391[模板]文艺平衡树(Splay) 平衡树解析 这里的Splay维护的显然不再是权值排序 现在按照的是序列中的编号排序(不过在这道题目里面就是权值诶...) 那么,继续 ...

  7. 平衡树——splay 三

    前文链接: 平衡树--splay 一 - yi_fan0305 - 博客园 (cnblogs.com) 平衡树--splay 二 - yi_fan0305 - 博客园 (cnblogs.com) 再补 ...

  8. 平衡树——splay 二

    上文传送门:平衡树--splay 一 - yi_fan0305 - 博客园 (cnblogs.com) OK,我们继续上文,来讲一些其他操作. 七.找排名为k的数 和treap的操作很像,都是通过比较 ...

  9. 平衡树——splay 一

    splay 一种平衡树,同时也是二叉排序树,与treap不同,它不需要维护堆的性质,它由Daniel Sleator和Robert Tarjan(没错,tarjan,又是他)创造,伸展树是一种自调整二 ...

  10. BZOJ3223: Tyvj 1729 文艺平衡树 [splay]

    3223: Tyvj 1729 文艺平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3595  Solved: 2029[Submit][Sta ...

随机推荐

  1. STM32串口打印输出乱码的解决办法

    前言 最近在试用uFUN开发板,下载配套的Demo程序,串口数据输出正常,当使用另一个模板工程,调用串口printf调试功能时,输出的却是乱码,最后发现是外部晶振频率不一样.很多STM32开发板都是使 ...

  2. [C#]使用Windows Form开发的百度网盘搜索工具

    BaiduDiskSearcher 用C#编写的百度网盘搜索工具(.NET4.0 & Visual Studio 2017) 功能 1.搜索任意名称的百度网盘共享文件 2.可以左键双击打开网盘 ...

  3. jenkins 构建后发送钉钉消息通知(插件)

    钉钉,越来越多的公司采用,那么我们在持续集成中,也可以直接选择钉钉插件的,在之前的博客中 ,对发送的钉钉消息进行了定制,那样的话会开启一个新的任务, 其实今天呢,我们可以直接安装一个插件就可以发送了, ...

  4. SSO单点登录_理解

    SSO核心意义就一句话:一处登录,处处登录:一处注销,处处注销.即:在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统. 很多人容易把SSO与OAuth搞混.这里简单说明一下: OA ...

  5. B. Equations of Mathematical Magic

    思路 打表找规律,发现结果是,2的(a二进制位为1总数)次方 代码 #include<bits/stdc++.h> using namespace std; #define ll long ...

  6. 个人博客作业Week2(9月30日)

    一.是否需要有代码规范 1.这些规范都是官僚制度下产生的浪费大家的编程时间.影响人们开发效率, 浪费时间的东西. 这些规范并不是一开始就有的,也不是由某个人规定的,代码规范是程序员们在不断地编程实践过 ...

  7. 《Linux内核分析》第五周学习总结

    <Linux内核分析>第五周学习总结                                  ——扒开系统调用的三层皮(下) 姓名:王玮怡 学号:20135116 1.给menu ...

  8. Linux内核分析——可执行程序的装载

    链接的过程 首先运行C预处理器cpp,将C的源程序(a.c)翻译成ASCII码的中间文件(a.i) 接着C编译器ccl,将a.i翻译成ASCII汇编语言文件a.s 接着运行汇编器as,将a.s翻译成可 ...

  9. Java开发异常

    1.org.apache.catalina.LifecycleException 报错信息如下: 警告: Error during context [/wxqhbcloud] restart org. ...

  10. IT行业创新的读后感

    一.什么是创新 创新是以新思维.新发明和新描述为特征的一种概念化过程.它原意有三层含义,第一,更新:第二,创造新的东西:第三,改变.创新是人类特有的认识能力和实践能力,是人类主观能动性的高级表现形式, ...