气死我了,调了一个下午+两节课,各种大大小小的错误,各种调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的更多相关文章

  1. [模板] 平衡树: Splay, 非旋Treap, 替罪羊树

    简介 二叉搜索树, 可以维护一个集合/序列, 同时维护节点的 \(size\), 因此可以支持 insert(v), delete(v), kth(p,k), rank(v)等操作. 另外, prev ...

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

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

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

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

  4. 平衡树模板【splay的实现】

    [平衡树splay实现] 无注释代码 #include<bits/stdc++.h> using namespace std; typedef long long LL; ,MAXN=1e ...

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

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

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

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

  7. 平衡树——splay 一

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

  8. hiho #1329 : 平衡树·Splay

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

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

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

随机推荐

  1. RabbitMQ系列(五)--高级特性

    在上一篇文章讲解MQ消息可靠性投递和幂等性中有提到confirm机制的重要性,现在更相信的说明一下 一.Confirm机制 Confirm就是消息确认,当Producer发送消息,如果Broker收到 ...

  2. SSH命令行传输文件到远程服务器

    Ubuntu操作系统 SCP命令 使用方式如下: 1.上传本地文件到远程服务器 scp /var/www/test.php root@192.168.0.101:/var/www/ 把本机/var/w ...

  3. 【原】Mysql存储关联数组

    $fruits= array("apple" => "苹果", "banana" => "香蕉"," ...

  4. 巩固JavaSE基础--IDEA完成实战项目

    PS:学习完JavaSE基础后,需要有一个项目来测试自己的学习成果,并加以巩固.所以在这里,就让我们来学习下“一本糊涂账”项目吧.(此项目来源于Java自学网站) 项目完成效果图一览

  5. 当点阵字库遇到3D

    早在遥远的DOS时代,点阵汉字库为计算机处理汉字起到了关键作用.当时的显示器在图形模式下的分辨率只有640x480甚至320x200,显示汉字直接使用点阵字库在屏幕上打点就可以了.如今的电脑屏幕甚至手 ...

  6. 「 hihoCoder 1014 」Trie 树

    标题真直接 题目大意 给你 $n$ 个字符串.存到一个字典中.又给你 $m$ 个询问,每个询问给一个字符串,在字典中查出有多少个字符串是以这个字符串为前缀. 解题思路 模板题啊 在每个点设置一个变量 ...

  7. 51nod 1118 机器人走方格【dp】

    M * N的方格,一个机器人从左上走到右下,只能向右或向下走.有多少种不同的走法?由于方法数量可能很大,只需要输出Mod 10^9 + 7的结果. 收起 输入 第1行,2个数M,N,中间用空格隔开.( ...

  8. <MySQL>入门三 数据定义语言 DDL

    -- DDL 数据定义语言 /* 库和表的管理 一.库的管理:创建.修改.删除 二.表的管理:创建.修改.删除 创建:create 修改:alter 删除:drop */ 1.库的管理 -- 库的管理 ...

  9. Python学习-if条件语句

    Python条件语句是通过一条或多条语句的执行结果(True或者False)来决定执行的代码块. 单分支条件语句 if 判断条件: 条件成立,执行该代码块.... 注意:与其他编程语言,如Java和C ...

  10. java用递归输出目录结构

    package com.janson.day20180827; import java.io.File; public class TestTreeStructureDirectory { publi ...