[BZOJ3224]Tyvj 1728 普通平衡树

试题描述

您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)

输入

第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)

输出

对于操作3,4,5,6每行输出一个数,表示对应答案

输入示例


输出示例


数据规模及约定

1.n的数据范围:n<=100000

2.每个数的数据范围:[-1e7,1e7]

题解

treap 模板题。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cctype>
#include <algorithm>
using namespace std; int read() {
int x = 0, f = 1; char c = getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
return x * f;
} #define maxn 100010
struct Node {
int v, r, siz;
Node() {}
Node(int _, int __): v(_), r(__) {}
} ns[maxn];
int rt, ToT, fa[maxn], ch[2][maxn];
void maintain(int o) {
ns[o].siz = 1;
for(int i = 0; i < 2; i++) if(ch[i][o])
ns[o].siz += ns[ch[i][o]].siz;
return ;
}
void rotate(int u) {
int y = fa[u], z = fa[y], l = 0, r = 1;
if(z) ch[ch[1][z]==y][z] = u;
if(ch[1][y] == u) swap(l, r);
fa[u] = z; fa[y] = u; fa[ch[r][u]] = y;
ch[l][y] = ch[r][u]; ch[r][u] = y;
maintain(y); maintain(u);
return ;
}
void insert(int& o, int v) {
if(!o) {
ns[o = ++ToT] = Node(v, rand());
return maintain(o);
}
bool d = v > ns[o].v;
insert(ch[d][o], v); fa[ch[d][o]] = o;
if(ns[ch[d][o]].r > ns[o].r) {
int t = ch[d][o];
rotate(t); o = t;
}
return maintain(o);
}
void del(int& o, int v) {
if(!o) return ;
if(ns[o].v == v) {
if(!ch[0][o] && !ch[1][o]) o = 0;
else if(!ch[0][o]) {
int t = ch[1][o]; fa[t] = fa[o]; o = t;
}
else if(!ch[1][o]) {
int t = ch[0][o]; fa[t] = fa[o]; o = t;
}
else {
bool d = ns[ch[1][o]].r > ns[ch[0][o]].r;
int t = ch[d][o]; rotate(t); o = t;
del(ch[d^1][o], v);
}
}
else {
bool d = v > ns[o].v ;
del(ch[d][o], v);
}
return maintain(o);
}
int qrank(int o, int v) {
if(!o) return 0;
int ls = ch[0][o] ? ns[ch[0][o]].siz : 0;
if(v > ns[o].v) return ls + 1 + qrank(ch[1][o], v);
return qrank(ch[0][o], v);
}
#define err -233333333
#define errm 233333333
int qkth(int o, int k) {
if(!o) return err;
int ls = ch[0][o] ? ns[ch[0][o]].siz : 0;
if(k == ls + 1) return ns[o].v;
if(k > ls + 1) return qkth(ch[1][o], k - ls - 1);
return qkth(ch[0][o], k);
}
int qlow(int o, int v) {
if(!o) return err;
bool d = v > ns[o].v;
if(d) return max(ns[o].v, qlow(ch[d][o], v));
return qlow(ch[d][o], v);
}
int qupp(int o, int v) {
if(!o) return errm;
bool d = v >= ns[o].v;
if(!d) return min(ns[o].v, qupp(ch[d][o], v));
return qupp(ch[d][o], v);
} int main() {
int q = read();
while(q--) {
int tp = read(), v = read();
if(tp == 1) insert(rt, v);
if(tp == 2) del(rt, v);
if(tp == 3) printf("%d\n", qrank(rt, v) + 1);
if(tp == 4) printf("%d\n", qkth(rt, v));
if(tp == 5) printf("%d\n", qlow(rt, v));
if(tp == 6) printf("%d\n", qupp(rt, v));
} return 0;
}

再贴一个替罪羊树版本的。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <cstring>
#include <string>
#include <map>
#include <set>
using namespace std; const int BufferSize = 1 << 16;
char buffer[BufferSize], *Head, *Tail;
inline char Getchar() {
if(Head == Tail) {
int l = fread(buffer, 1, BufferSize, stdin);
Tail = (Head = buffer) + l;
}
return *Head++;
}
int read() {
int x = 0, f = 1; char c = Getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); }
return x * f;
} #define maxn 100010
#define oo 2147483647
struct Node {
int v, siz, reas, mx, mn;
bool del;
Node() {}
Node(int _): v(_), del(0) {}
} ns[maxn];
int rt, ToT, fa[maxn], ch[maxn][2];
void maintain(int o) {
ns[o].siz = ns[o].del ^ 1; ns[o].reas = 1;
ns[o].mx = ns[o].del ? -oo : ns[o].v;
ns[o].mn = ns[o].del ? oo : ns[o].v;
for(int i = 0; i < 2; i++) if(ch[o][i])
ns[o].siz += ns[ch[o][i]].siz,
ns[o].reas += ns[ch[o][i]].reas,
ns[o].mx = max(ns[o].mx, ns[ch[o][i]].mx),
ns[o].mn = min(ns[o].mn, ns[ch[o][i]].mn);
return ;
}
const double Bili = .6;
bool unbal(int o) {
return max(ch[o][0] ? ns[ch[o][0]].reas : 0, ch[o][1] ? ns[ch[o][1]].reas : 0) > Bili * ns[o].reas;
}
int rb;
void insert(int& o, int v) {
if(!o) {
ns[o = ++ToT] = Node(v);
return maintain(o);
}
bool d = v > ns[o].v;
insert(ch[o][d], v); fa[ch[o][d]] = o; maintain(o);
if(unbal(o)) rb = o;
return ;
}
int cntn, get[maxn];
void getnode(int o) {
if(!o) return ;
getnode(ch[o][0]);
if(!ns[o].del) get[++cntn] = o;
getnode(ch[o][1]);
fa[o] = ch[o][0] = ch[o][1] = 0;
return ;
}
void build(int& o, int l, int r) {
if(l > r){ o = 0; return ; }
int mid = l + r >> 1; o = get[mid];
build(ch[o][0], l, mid - 1); build(ch[o][1], mid + 1, r);
if(ch[o][0]) fa[ch[o][0]] = o;
if(ch[o][1]) fa[ch[o][1]] = o;
return maintain(o);
}
void rebuild(int& o) {
cntn = 0; getnode(o);
build(o, 1, cntn);
return ;
}
void Insert(int v) {
rb = 0; insert(rt, v);
if(!rb) return ;
int frb = fa[rb];
if(!frb) rebuild(rt), fa[rt] = 0;
else if(ch[frb][0] == rb) rebuild(ch[frb][0]), fa[ch[frb][0]] = frb;
else rebuild(ch[frb][1]), fa[ch[frb][1]] = frb;
return ;
}
bool unbal2(int o) {
return Bili * ns[o].reas > ns[o].siz;
}
void del(int o, int k) {
if(!o) return ;
int ls = ch[o][0] ? ns[ch[o][0]].siz : 0;
if(k == ls + 1 && !ns[o].del) {
ns[o].del = 1; maintain(o);
if(unbal2(o)) rb = o;
return ;
}
if(k > ls + (ns[o].del ^ 1)) {
del(ch[o][1], k - ls - (ns[o].del ^ 1)); maintain(o);
if(unbal2(o)) rb = o;
return ;
}
del(ch[o][0], k); maintain(o);
if(unbal2(o)) rb = o;
return ;
}
int Find(int o, int v) {
if(!o) return 0;
int ls = ch[o][0] ? ns[ch[o][0]].siz : 0;
if(v <= ns[o].v) return Find(ch[o][0], v);
return ls + (ns[o].del ^ 1) + Find(ch[o][1], v);
}
void Delete(int v) {
int id = Find(rt, v) + 1;
rb = 0; del(rt, id);
int tmp = ns[rt].reas;
if(!rb) return ;
int frb = fa[rb];
if(!frb) rebuild(rt), fa[rt] = 0;
else if(ch[frb][0] == rb) rebuild(ch[frb][0]), fa[ch[frb][0]] = frb;
else rebuild(ch[frb][1]), fa[ch[frb][1]] = frb;
return ;
}
int qkth(int o, int k) {
if(!o) return 0;
int ls = ch[o][0] ? ns[ch[o][0]].siz : 0;
if(k == ls + 1 && !ns[o].del) return ns[o].v;
if(k > ls + (ns[o].del ^ 1)) return qkth(ch[o][1], k - ls - (ns[o].del ^ 1));
return qkth(ch[o][0], k);
}
int qlow(int o, int v) {
if(!o) return -oo;
if(ns[o].v < v) return max(max(ns[o].del ? -oo : ns[o].v, ch[o][0] ? ns[ch[o][0]].mx : -oo), qlow(ch[o][1], v));
return qlow(ch[o][0], v);
}
int qupp(int o, int v) {
if(!o) return oo;
if(ns[o].v > v) return min(min(ns[o].del ? oo : ns[o].v, ch[o][1] ? ns[ch[o][1]].mn : oo), qupp(ch[o][0], v));
return qupp(ch[o][1], v);
} int main() {
int q = read();
while(q--) {
int tp = read(), x = read();
if(tp == 1) Insert(x);
if(tp == 2) Delete(x);
if(tp == 3) printf("%d\n", Find(rt, x) + 1);
if(tp == 4) printf("%d\n", qkth(rt, x));
if(tp == 5) printf("%d\n", qlow(rt, x));
if(tp == 6) printf("%d\n", qupp(rt, x));
} return 0;
}

懒惰删除真的一点都不懒惰!!!打了删除标记反而更难处理了。。。太多细节要考虑。

再贴一个 fhq treap 的版本。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <cassert>
using namespace std;
#define rep(i, s, t) for(int i = (s), mi = (t); i <= mi; i++)
#define dwn(i, s, t) for(int i = (s), mi = (t); i >= mi; i--) const int BufferSize = 1 << 16;
char buffer[BufferSize], *Head, *Tail;
inline char Getchar() {
if(Head == Tail) {
int l = fread(buffer, 1, BufferSize, stdin);
Tail = (Head = buffer) + l;
}
return *Head++;
}
int read() {
int x = 0, f = 1; char c = Getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); }
return x * f;
} #define maxn 100010
#define oo 2147483647
#define pii pair <int, int>
#define x first
#define y second
#define mp(x, y) make_pair(x, y) struct Node {
int v, r, siz;
Node() {}
Node(int _v): v(_v), r(rand()), siz(1) {}
} ns[maxn];
int ToT, rt, ch[maxn][2]; void maintain(int o) {
if(!o) return ;
ns[o].siz = 1;
if(ch[o][0]) ns[o].siz += ns[ch[o][0]].siz;
if(ch[o][1]) ns[o].siz += ns[ch[o][1]].siz;
return ;
}
int merge(int a, int b) { // max{a} <= min{b}
if(!a) return maintain(b), b;
if(!b) return maintain(a), a;
if(ns[a].r > ns[b].r) return ch[a][1] = merge(ch[a][1], b), maintain(a), a;
return ch[b][0] = merge(a, ch[b][0]), maintain(b), b;
}
pii split(int o, int k) {
if(!o) return mp(0, 0);
if(!k) return mp(0, o);
int ls = ch[o][0] ? ns[ch[o][0]].siz : 0;
if(k <= ls) {
pii pr = split(ch[o][0], k);
ch[o][0] = pr.y; maintain(o);
return mp(pr.x, o);
}
pii pr = split(ch[o][1], k - ls - 1);
ch[o][1] = pr.x; maintain(o);
return mp(o, pr.y);
}
int Find(int o, int v) {
if(!o) return 0;
int ls = ch[o][0] ? ns[ch[o][0]].siz : 0;
if(v <= ns[o].v) return Find(ch[o][0], v);
return ls + 1 + Find(ch[o][1], v);
}
void Insert(int v) {
int rnk = Find(rt, v);
pii pr = split(rt, rnk);
ns[++ToT] = Node(v);
rt = merge(pr.x, ToT);
rt = merge(rt, pr.y);
return ;
}
void Delete(int& o, int v) {
if(!o) return ;
if(ns[o].v == v) return (void)(o = merge(ch[o][0], ch[o][1]));
if(v < ns[o].v) Delete(ch[o][0], v);
else Delete(ch[o][1], v);
return maintain(o);
}
int qkth(int o, int k) {
assert(o);
int ls = ch[o][0] ? ns[ch[o][0]].siz : 0;
if(k == ls + 1) return ns[o].v;
if(k <= ls) return qkth(ch[o][0], k);
return qkth(ch[o][1], k - ls - 1);
}
int qpre(int o, int v) {
if(!o) return -oo;
if(ns[o].v < v) return max(ns[o].v, qpre(ch[o][1], v));
return qpre(ch[o][0], v);
}
int qnxt(int o, int v) {
if(!o) return oo;
if(ns[o].v > v) return min(ns[o].v, qnxt(ch[o][0], v));
return qnxt(ch[o][1], v);
} int main () {
srand(5);
int q = read();
while(q--) {
int tp = read();
if(tp == 1) Insert(read());
if(tp == 2) Delete(rt, read());
if(tp == 3) printf("%d\n", Find(rt, read()) + 1);
if(tp == 4) printf("%d\n", qkth(rt, read()));
if(tp == 5) printf("%d\n", qpre(rt, read()));
if(tp == 6) printf("%d\n", qnxt(rt, read()));
} return 0;
}

[BZOJ3224]Tyvj 1728 普通平衡树的更多相关文章

  1. bzoj3224: Tyvj 1728 普通平衡树(平衡树)

    bzoj3224: Tyvj 1728 普通平衡树(平衡树) 总结 a. cout<<(x=3)<<endl;这句话输出的值是3,那么对应的,在splay操作中,当父亲不为0的 ...

  2. bzoj3224 Tyvj 1728 普通平衡树(名次树+处理相同)

    3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 5354  Solved: 2196[Submit][Sta ...

  3. bzoj3224: Tyvj 1728 普通平衡树(splay)

    3224: Tyvj 1728 普通平衡树 题目:传送门 题解: 啦啦啦啦又来敲个模版水经验啦~ 代码: #include<cstdio> #include<cstring> ...

  4. 【权值线段树】bzoj3224 Tyvj 1728 普通平衡树

    一个板子. #include<cstdio> #include<algorithm> using namespace std; #define N 100001 struct ...

  5. [BZOJ3224] [Tyvj 1728] 普通平衡树 (treap)

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

  6. BZOJ3224 Tyvj 1728 普通平衡树(Treap)

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

  7. 【权值分块】bzoj3224 Tyvj 1728 普通平衡树

    权值分块和权值线段树的思想一致,离散化之后可以代替平衡树的部分功能. 部分操作的时间复杂度: 插入 删除 全局排名 全局K大 前驱 后继 全局最值 按值域删除元素 O(1) O(1) O(sqrt(n ...

  8. 绝对是全网最好的Splay 入门详解——洛谷P3369&BZOJ3224: Tyvj 1728 普通平衡树 包教包会

    平衡树是什么东西想必我就不用说太多了吧. 百度百科: 一个月之前的某天晚上,yuli巨佬为我们初步讲解了Splay,当时接触到了平衡树里的旋转等各种骚操作,感觉非常厉害.而第二天我调Splay的模板竟 ...

  9. BZOJ3224——Tyvj 1728 普通平衡树

    1.题目大意:数据结构题,是treap,全都是treap比较基本的操作 2.分析:没啥思考的 #include <cstdio> #include <cstdlib> #inc ...

随机推荐

  1. Could not load type 'System.Web.Mvc.ViewPage<dynamic>' in asp.net mvc2 after publishing the website

    在WebConfig里 找到 <pages></pages> <pages pageParserFilterType="System.Web.Mvc.ViewT ...

  2. 《中国文明史》系列—外柔 VS 内厉

    读启良的<中国文明史>,里面有谈到外柔而内厉——中国政府自古以来奉行的准则.大致意思是说,我华夏民族对待周边民族,历来是很友好的,即所谓的“柔”,而对待自己人,向来是“刚”或曰“厉”的. ...

  3. 如何用TypeScript开发微信小程序

    微信小程序来了!这个号称干掉传统app的玩意儿虽然目前处于内测阶段,不过目前在应用号的官方文档里已经放出了没有内测号也能使用的模拟器了. 工具和文档可以参考官方文档:https://mp.weixin ...

  4. Chrome浏览器调试,console简述

    作为一个前端开发者,不可避免的需要进行各种各样的调试. 在谷歌浏览器出来以前,火狐的firebug是特别有名的一款调试工具,不过自从谷歌浏览器诞生以来,其自带的开发者工具足以媲美firebug,某种程 ...

  5. 【WPF】GridLengthAnimation

    参考 : http://zhidao.baidu.com public class GridLengthAnimation : AnimationTimeline { public static re ...

  6. C语言中struct位域的定义和使用

    位域的定义和使用 有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位.例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可.为了节省存储空间,并使处理简便,C语言又 ...

  7. 滑动验证的设计与实现J2EE

    滑动验证的设计与实现J2EE 注:本博文为博主原创,转载请注明出处. 项目源码地址:https://github.com/zhangxy1035/Verify 本篇博文的主要目录如下: 一.项目简介二 ...

  8. cocoapods安装

    什么是cocoapods CocoaPods是一个用来帮助我们管理第三方依赖库的工具.它可以解决库与库之间的依赖关系,下载库的源代码,同时通过创建一个Xcode的workspace来将这些第三方库和我 ...

  9. Beta阶段第六次Scrum Meeting

    情况简述 BETA阶段第六次Scrum Meeting 敏捷开发起始时间 2016/12/16 00:00 敏捷开发终止时间 2016/12/17 00:00 会议基本内容摘要 平稳推进 参与讨论人员 ...

  10. POJ 2253 Frogger(Dijkstra)

    传送门 Frogger Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 39453   Accepted: 12691 Des ...