[模板]平衡树splay
气死我了,调了一个下午+两节课,各种大大小小的错误,各种调QAQ,最后总之是调出来了.
其实就是一个双旋操作,然后其他就是左儿子<当前节点<右儿子,剩下就是细节了.
题干:
题目描述
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
插入xxx数
删除xxx数(若有多个相同的数,因只删除一个)
查询xxx数的排名(排名定义为比当前数小的数的个数+++。若有多个相同的数,因输出最小的排名)
查询排名为xxx的数
求xxx的前驱(前驱定义为小于xxx,且最大的数)
求xxx的后继(后继定义为大于xxx,且最小的数)
输入输出格式
输入格式:
第一行为nnn,表示操作的个数,下面nnn行每行有两个数optoptopt和xxx,optoptopt表示操作的序号( ≤opt≤ \leq opt \leq ≤opt≤ )
输出格式:
对于操作3,,,,,,,,,6每行输出一个数,表示对应答案
输入输出样例
输入样例#: 复制
输出样例#: 复制
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<algorithm>
#include<vector>
#include<cstring>
using namespace std;
#define duke(i,a,n) for(int i = a;i <= n;i++)
#define lv(i,a,n) for(int i = a;i >= n;i--)
#define clean(a) memset(a,0,sizeof(a))
#define pr pair<int,int>
#define mp make_pair
const int INF = ;
const double eps = 1e-;
typedef long long ll;
typedef double db;
template <class T>
void read(T &x)
{
char c;
bool op = ;
while(c = getchar(), c < '' || c > '')
if(c == '-') op = ;
x = c - '';
while(c = getchar(), c >= '' && c <= '')
x = x * + c - '';
if(op) x = -x;
}
template <class T>
void write(T x)
{
if(x < ) putchar('-'), x = -x;
if(x >= ) write(x / );
putchar('' + x % );
}
struct node
{
int v,fa,ch[],sum,recy;
}e[];
int n,points,N;
#define root e[0].ch[1]
void update(int x)
{
e[x].sum = e[e[x].ch[]].sum + e[e[x].ch[]].sum + e[x].recy;
}
int iden(int x)
{
return e[e[x].fa].ch[] == x ? : ;
}
void connect(int x,int f,int son)
{
e[x].fa = f;
e[f].ch[son] = x;
}
void rotate(int x)
{
int y = e[x].fa;
int mroot = e[y].fa;
int mrootson = iden(y);
int yson = iden(x);
int b = e[x].ch[yson ^ ];
connect(b,y,yson);
connect(y,x,yson ^ );
connect(x,mroot,mrootson);
update(y);
update(x);
}
void splay(int at,int to)
{
to = e[to].fa;
while(e[at].fa != to)
{
int up = e[at].fa;
if(e[up].fa == to) rotate(at);
else if(iden(up) == iden(at))
{
rotate(up);
rotate(at);
}
else
{
rotate(at);
rotate(at);
}
}
}
int crepoint(int v,int fa)
{
n++;
e[n].v = v;
e[n].fa = fa;
// cout<<v<<" "<<fa<<endl;
e[n].sum = e[n].recy = ;
return n;
}
void destroy(int x)
{
e[x].v = e[x].ch[] = e[x].ch[] = e[x].sum = e[x].fa = e[x].recy = ;
if(x == n)
n--;
while(e[n].v == && e[n].sum == && n > )
n--;
}
int find(int v)
{
int now = root;
while(true)
{
if(e[now].v == v)
{
splay(now,root);
return now;
}
int nxt = v < e[now].v ? : ;
if(!e[now].ch[nxt]) return ;
now = e[now].ch[nxt];
}
}
int build(int v)
{
points++;
// cout<<v<<endl;
if(n == )
{
root = ;
crepoint(v,);
}
else
{
int now = root;
while(true)
{
// cout<<now<<endl;
e[now].sum++;
if(v == e[now].v)
{
e[now].recy++;
return now;
}
int nxt = v < e[now].v ? : ;
if(!e[now].ch[nxt])
{
crepoint(v,now);
e[now].ch[nxt] = n;
return n;
}
now = e[now].ch[nxt];
}
}
return ;
}
void push(int v)
{
int add = build(v);
if( rand() % == )
splay(add,root);
}
void pop(int v)
{
int deal = find(v);
if(!deal) return;
points--;
if(e[deal].recy > )
{
e[deal].recy--;
e[deal].sum--;
return;
}
if(!e[deal].ch[])
{
root = e[deal].ch[];
e[root].fa = ;
}
else
{
int lef = e[deal].ch[];
while(e[lef].ch[]) lef = e[lef].ch[];
splay(lef,e[deal].ch[]);
int rig = e[deal].ch[];
connect(rig,lef,);connect(lef,,);
update(lef);
}
destroy(deal);
}
int Rank(int v)
{
int ans = ,now = root;
// cout<<v<<endl;
while(true)
{
if(e[now].v == v)
return ans + e[e[now].ch[]].sum + ;
if(now == ) return ;
if(v < e[now].v) now = e[now].ch[];
else
{
ans = ans + e[e[now].ch[]].sum + e[now].recy;
now = e[now].ch[];
}
}
//if(now) splay(now,root);
return ;
}
int atRank(int x)
{
if(x > points) return -INF;
int now = root;
// cout<<root<<endl;
while(true)
{
// cout<<now<<endl;
int minused = e[now].sum - e[e[now].ch[]].sum;
if(x > e[e[now].ch[]].sum && x <= minused) break;
if(x < minused) now = e[now].ch[];
else
{
x = x - minused;
now = e[now].ch[];
}
}
//splay(now,root);
return e[now].v;
}
int upper(int v)
{
int now = root;
int result = INF;
while(now)
{
if(e[now].v > v && e[now].v < result) result = e[now].v;
if(v < e[now].v) now = e[now].ch[];
else
now = e[now].ch[];
}
return result;
}
int lower(int v)
{
int now = root;
int result = -INF;
while(now)
{
// cout<<now<<endl;
if(e[now].v < v && e[now].v > result)
result = e[now].v;
if(v > e[now].v) now = e[now].ch[];
else
now = e[now].ch[];
}
return result;
}
void Szcheck( int pos ){
if( e[pos].ch[] ) Szcheck(e[pos].ch[]);
if( e[pos].ch[] ) Szcheck(e[pos].ch[]);
if( e[e[pos].ch[]].sum + + e[e[pos].ch[]].sum != e[pos].sum ){
cout << "Size Error At Pos" << pos << endl;
}
}
void gg()
{
cout<<n<<endl;
duke(i,,n)
{
printf("%d ",e[i].v);
}
puts("");
}
int main()
{
// freopen("3369.in","r",stdin);
read(N);
duke(i,,N)
{
int opt,value;
// cout<<endl<<i<<endl;
read(opt);read(value);
// if(opt != 1 && opt != 2)
// cout<<opt<<" "<<value<<endl;
switch(opt)
{
case : push(value);break;
case : pop(value);break;
case : cout<<Rank(value)<<endl;break;
case : {cout<<atRank(value)<<endl;}break;
case : cout<<lower(value)<<endl;break;
case : cout<<upper(value)<<endl;break;
case : gg();
}
//Szcheck(root);
// cout<<i<<endl;
}
return ;
}
/*
10
1 106465
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
4 1
*/
代码有点长...
[模板]平衡树splay的更多相关文章
- [模板] 平衡树: Splay, 非旋Treap, 替罪羊树
简介 二叉搜索树, 可以维护一个集合/序列, 同时维护节点的 \(size\), 因此可以支持 insert(v), delete(v), kth(p,k), rank(v)等操作. 另外, prev ...
- 【阶梯报告】洛谷P3391【模板】文艺平衡树 splay
[阶梯报告]洛谷P3391[模板]文艺平衡树 splay 题目链接在这里[链接](https://www.luogu.org/problemnew/show/P3391)最近在学习splay,终于做对 ...
- luoguP3391[模板]文艺平衡树(Splay) 题解
链接一下题目:luoguP3391[模板]文艺平衡树(Splay) 平衡树解析 这里的Splay维护的显然不再是权值排序 现在按照的是序列中的编号排序(不过在这道题目里面就是权值诶...) 那么,继续 ...
- 平衡树模板【splay的实现】
[平衡树splay实现] 无注释代码 #include<bits/stdc++.h> using namespace std; typedef long long LL; ,MAXN=1e ...
- 【BZOJ3224】Tyvj 1728 普通平衡树 Splay
Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数 ...
- BZOJ3224/洛谷P3391 - 普通平衡树(Splay)
BZOJ链接 洛谷链接 题意简述 模板题啦~ 代码 //普通平衡树(Splay) #include <cstdio> int const N=1e5+10; int rt,ndCnt; i ...
- 平衡树——splay 一
splay 一种平衡树,同时也是二叉排序树,与treap不同,它不需要维护堆的性质,它由Daniel Sleator和Robert Tarjan(没错,tarjan,又是他)创造,伸展树是一种自调整二 ...
- hiho #1329 : 平衡树·Splay
#1329 : 平衡树·Splay 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Ho:小Hi,上一次你跟我讲了Treap,我也实现了.但是我遇到了一个关键的问题. ...
- Hihocoder 1329 平衡树·Splay(平衡树)
Hihocoder 1329 平衡树·Splay(平衡树) Description 小Ho:小Hi,上一次你跟我讲了Treap,我也实现了.但是我遇到了一个关键的问题. 小Hi:怎么了? 小Ho:小H ...
随机推荐
- CPU总线
总线(Bus)是计算机各种功能部件之间传送信息的公共通信干线,它是由导线组成的传输线束.按照计算机所传输的信息种类,计算机的总线可以划分为数据总线.地址总线和控制总线,分别用来传输数据.数据地址和控制 ...
- 以POST方式推送JSON数据,并接收返回的服务器消息
private static string GetResult(string jsonString, string type) { string url = GetUrl(type); string ...
- 模板—treap
#include<iostream> #include<cstdio> #include<cstdlib> #define INF 0x7fffffff using ...
- myeclipse工具常用的用法
1. 自动提示:窗口->首选项->Java->编辑器->内容辅助->自动激活,在下面的“Java的自动激活触发器里面填上“.abcdefghijklmnopqrstuv ...
- POJ P2096 Collecting Bugs
思路 分类讨论,不妨先设$DP[i][j]$表示已经发现$i$种子系统中有$n$种$bug$无非只有四种情况 发现的$bug$在旧的系统旧的分类,概率$p1$是$(i/s)*(j/n)$. 发现的$b ...
- ROS lesson 1
ROS ROS官网 ROS 简介 ROS 是 Robot Operation System 的简写,并且 他诞生在2000年后,至今有10余年了,运行在 Linux(Ubuntu) 上 ROS 不是 ...
- 百练4103:踩方格(DFS)
描述 有一个方格矩阵,矩阵边界在无穷远处.我们做如下假设:a. 每走一步时,只能从当前方格移动一格,走到某个相邻的方格上:b. 走过的格子立即塌陷无法再走第二次:c. 只能向北.东. ...
- 【Codeforces 484A】Bits
[链接] 我是链接,点我呀:) [题意] 让你求出l~r当中二进制表示1的个数最多的数x [题解] 最多有64位 我们可以从l开始一直增大到r 怎么增大? 找到l的二进制表示当中0所在的位置 假设i这 ...
- Leetcode 92.反转链表
92.反转链表 反转从位置 m 到 n 的链表.请使用一趟扫描完成反转. 说明:1 ≤ m ≤ n ≤ 链表长度. 示例: 输入: 1->2->3->4->5->NULL ...
- [luoguP2896] [USACO08FEB]一起吃饭Eating Together(DP)
传送门 由于 Di 只有 3 种情况,那么就很简单了 f[i][j][0] 表示前 i 个,且第 i 个变成 j 的 递增序列最小修改次数 f[i][j][1] 表示前 i 个,且第 i 个变成 j ...