Problem 平衡树 Splay

题目大意

  维护一个数列,支持三种操作。

  操作1:添加一个数x。

  操作2:询问不超过x的最大的数。

  操作三:删除大小在区间【a,b】内的数。

解题分析

  和上一题相比,多了一个删除的操作。

  首先将a的前驱节点x旋转到根,然后将b的后驱节点y旋转到x的右孩子,这样所有大小在【a,b】内的数均位于y的左子树内,直接将其删掉就可以了。

  为了防止找不到x和y,在初始化时向树中插入一个极大值和一个极小值。

参考程序

 #include <bits/stdc++.h>
using namespace std; struct node{
int val;
node *left,*right,*father;
node(int val_=,node* father_=NULL,node* left_=NULL,node* right_=NULL)
{
val=val_; father=father_; left=left_; right=right_;
}
}*rt,*t1,*t2; void search(node *now)
{
cout<<now<<" "<<now->val<<" "<<now->left<<" "<<now->right<<" "<<now->father<<endl;
if (now->left) search(now->left);
if (now->right) search(now->right);
} void pushup(node *x)
{
} void right(node* x,node* &rt)
{
node *y=x->father,*z=y->father;
if (y==rt) rt=x;
else if (z->left==y) z->left=x; else z->right=x; //需要判断是左右孩子
x->father=z; y->father=x; if (x->right) x->right->father=y; //防止对空指针进行操作
y->left=x->right; x->right=y;
pushup(y); pushup(x);
} void left(node* x,node* &rt)
{
node *y=x->father,*z=y->father;
if (y==rt) rt=x;
else if (z->left==y) z->left=x; else z->right=x;
x->father=z; y->father=x; if (x->left) x->left->father=y;
y->right=x->left; x->left=y;
pushup(y); pushup(x);
} void splay(node* x,node* &rt)
{
while (x!=rt)
{
node *y=x->father, *z=y->father;
if (y==rt)
{
if (x==y->left) right(x,rt);
else left(x,rt);
}
else
{
if (y==z->left)
if (x==y->left) { right(y,rt); right(x,rt); }
else { left(x,rt); right(x,rt); }
else
if (x==y->right) { left(y,rt); left(x,rt); }
else { right(x,rt); left(x,rt); }
}
}
} void insert(int val,node* &now,node *last)
{
if (now==NULL)
{
now=new node(val,last);
splay(now,rt);
return;
}
if (val < now->val) insert(val,now->left,now); else //else还是要加的 返回的时候树的形态已经改变了
if (val > now->val) insert(val,now->right,now);
} int get(int val,node *x)
{
int res=-<<;
while (x!=NULL)
{
if (x->val>val) x=x->left;
else
{
res=max(res,x->val);
x=x->right;
}
}
return res;
} void find_1(int val,node *x)
{
if (x==NULL) return;
if (x->val>=val) find_1(val,x->left);
else {t1=x; find_1(val,x->right);}
} void find_2(int val,node *x)
{
if (x==NULL) return;
if (x->val<=val) find_2(val,x->right);
else {t2=x; find_2(val,x->left);}
} void work(int l,int r)
{
t1=t2=NULL;
find_1(l,rt); splay(t1,rt);
find_2(r,rt->right); splay(t2,rt->right);
rt->right->left=NULL;
} int main()
{
int n;
rt=NULL;
scanf("%d",&n);
insert(<<,rt,NULL); insert(-<<,rt,NULL);
for (int i=;i<=n;i++)
{
char s[]; int x,y;
scanf("%s%d",s,&x);
if (s[]=='I') insert(x,rt,NULL);
if (s[]=='Q') cout<<get(x,rt)<<endl;
if (s[]=='D')
{
scanf("%d",&y);
if (x>y) swap(x,y);
work(x,y);
}
}
}

Hihocoder 1329(splay)的更多相关文章

  1. Hihocoder 1325 (splay)

    Problem 平衡树 Treap 题目大意 维护一个数列,支持两种操作. 操作1:添加一个数x. 操作2:询问不超过x的最大的数. 解题分析 尝试了一下用指针来写splay,感觉写起来还是比较流畅的 ...

  2. Hihocoder 1333 (splay)

    Problem 平衡树 splay2 题目大意 维护一个序列,支持四种操作: 操作1:添加一个数,编号为x,权值为y. 操作2:删除编号在区间[x,y]内的数. 操作3:将编号在区间[x,y]内的数的 ...

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

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

  4. 【BZOJ3506】排序机械臂(Splay)

    [BZOJ3506]排序机械臂(Splay) 题面 神TMBZOJ没有题面,感谢SYC的题面 洛谷的题面也不错 题解 对于每次旋转的物体 显然可以预处理出来 现在只要模拟旋转操作就行了 至于在哪里放标 ...

  5. 【BZOJ1500】【NOI2005】维修数列(Splay)

    [BZOJ1500][NOI2005]维修数列(Splay) 题面 不想再看见这种毒瘤题,自己去BZOJ看 题解 Splay良心模板题 真的很简单 我一言不发 #include<iostream ...

  6. 【BZOJ1862】[ZJOI2006]游戏排名系统 (Splay)

    [BZOJ1862][ZJOI2006]游戏排名系统 (Splay) 题面 BZOJ 洛谷 题解 双倍经验题

  7. 【BZOJ1056】[HAOI2008]排名系统(Splay)

    [BZOJ1056][HAOI2008]排名系统(Splay) 题面 BZOJ 洛谷 题解 \(Splay\)随便维护一下就好了,至于名字什么的,我懒得手写哈希表了,直接哈希之后拿\(map\)压. ...

  8. 【BZOJ2329】括号修复(Splay)

    [BZOJ2329]括号修复(Splay) 题面 BZOJ 洛谷 题解 本来想着用线段树来写 但是有一个区间翻转 所以不能用线段树了,就只能用平衡树 然后直接\(Splay\)就好了 注意一下几个标记 ...

  9. P3391 【模板】文艺平衡树(Splay)新板子

    P3391 [模板]文艺平衡树(Splay) 题目背景 这是一道经典的Splay模板题——文艺平衡树. 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转 ...

随机推荐

  1. SpringBoot整合SpringSecurity简单案例

    在我们开发项目的过程中经常会用到一些权限管理框架,Java领域里边经常用的可能就是shiro了,与之对应的还有SpringSecurity,SpringSecurity可以说是非常强大,与Spring ...

  2. Linux学习笔记之Linux用户与用户组、文件操作命令、文件权限剖析

    1.用户与用户组 Linux是一个多用户操作系统,通过用户与用户组的概念,可以实现保证安全性和隐私性.任何一个文件都具有User.Group.Others三个权限. 文件拥有者(Linux下所有的东西 ...

  3. [转]C语言文件操作函数大全(超详细)

    fopen(打开文件)相关函数 open,fclose表头文件 #include<stdio.h>定义函数 FILE * fopen(const char * path,const cha ...

  4. .Net MVC之间的关系以及如何运用

    .Net MVC组成部分:视图(views)模型(model)控制器(controller)以及路由(RouteConfig),视图跟模型的数据不进行直接的交互,他们是通过控制器进行视图模型之间的数据 ...

  5. TCPClient、TCPListener的用法

    支持Http.Tcp和Udp的类组成了TCP/IP三层模型(请求响应层.应用协议层.传输层)的中间层-应用协议层,该层的类比位于最底层的Socket类提供了更高层次的抽象,它们封装 TCP 和 UDP ...

  6. C语言用指针输出数组里的值

    因为*(arr)是指arr数组内存编号所对应的首地址的值,即arr[0]的值.所以用*(arr+i)可以实现遍历整个数组.

  7. 【ZT】在微信上有哪些高情商的说话方式 | M周刊(听语音需要60秒,看文字只需10秒)

    https://baijiahao.baidu.com/s?id=1590547145580792217&wfr=spider&for=pc https://yuedu.baidu.c ...

  8. 微信小程序组件解读和分析:五、text文本

    text文本组件说明: text 文本就是微信小程序中显示出来的文本. text文本组件的示例代码运行效果如下: 下面是WXML代码: [XML] 纯文本查看 复制代码 ? 1 2 3 4 <v ...

  9. 解决 HTTP Status 500 - Unable to show problem report: freemarker.core.InvalidReferenceException:

    HTTP Status 500 - Unable to show problem report: freemarker.core.InvalidReferenceException: The foll ...

  10. 07C语言程序语句

    C语言程序语句 判断语句 if(表达式) {语句} #include <stdio.h> int main(){ printf("请输入2个数字:"); int a,b ...