题目描述

这是一道模板题,其数据比「普通平衡树」更强。

如未特别说明,以下所有数据均为整数。

维护一个多重集 S ,初始为空,有以下几种操作:

把 x 加入 S

删除 S 中的一个 x,保证删除的 x 一定存在

求 S 中第 k 小

求 S 中有多少个元素小于 x

求 S 中小于 x 的最大数

求 S 中大于 x 的最小数

操作共 n 次。

输入格式

第一行一个整数 n,表示共有 n 次操作 。

接下来 n 行,每行为以下几种格式之一 :

0 x,把 x 加入 S

1 x,删除 S 中的一个 x,保证删除的数在 S 中一定存在

2 k,求 S 中第 k 小的数,保证要求的数在 S 中一定存在

3 x,求 S 中有多少个数小于 x

4 x,求 S 中小于 x 的最大数,如果不存在,输出 −1

5 x,求 S 中大于 x 的最小数,如果不存在,输出 −1

输出格式

对于每次询问,输出单独一行表示答案。

样例

样例输入

5

0 3

0 4

2 2

1 4

3 3

样例输出

4

0

数据范围与提示

$ 1 \leq n \leq 3 \times 10 ^ 5, 0 \leq x \leq 10 ^ 9$


思路

平衡数已经烂大街了

我就来讲讲bit怎么维护全序集吧

除了bit的常规操作,核心技能只有一个

就是找序列的第k大

这个东西是可以在树状数组上二分的

你会发现对于任何一个bit上的节点

它左子树上的任何一个节点都是对应右子树上的一个节点加上一个二进制位得到的

并且这个二进制位恰好是这个节点儿子的层数所对应的二进制位

所以就可以直接看这个二进制位到底要不要选

在bit上二分并迭代就可以了

好神仙的操作啊


//Author: dream_maker
#include<bits/stdc++.h>
using namespace std;
//----------------------------------------------
//typename
typedef long long ll;
//convenient for
#define fu(a, b, c) for (int a = b; a <= c; ++a)
#define fd(a, b, c) for (int a = b; a >= c; --a)
#define fv(a, b) for (int a = 0; a < (signed)b.size(); ++a)
//inf of different typename
const int INF_of_int = 1e9;
const ll INF_of_ll = 1e18;
//fast read and write
template <typename T>
void Read(T &x) {
bool w = 1;x = 0;
char c = getchar();
while (!isdigit(c) && c != '-') c = getchar();
if (c == '-') w = 0, c = getchar();
while (isdigit(c)) {
x = (x<<1) + (x<<3) + c -'0';
c = getchar();
}
if (!w) x = -x;
}
template <typename T>
void Write(T x) {
if (x < 0) {
putchar('-');
x = -x;
}
if (x > 9) Write(x / 10);
putchar(x % 10 + '0');
}
//----------------------------------------------
//树状数组维护全序集
const int N = 1e6 + 10;
int tot = 0, n, up = 1;
int a[N], b[N], op[N];
int bit[N], lowbit[N];
inline void insert(int vl) {
for (; vl <= tot; vl += lowbit[vl]) ++bit[vl];
}
inline void del(int vl) {
for (; vl <= tot; vl += lowbit[vl]) --bit[vl];
}
inline int query(int vl) {
int res = 0;
for (; vl; vl -= lowbit[vl]) res += bit[vl];
return res;
}
inline int kth(int vl) {
int res = 0;
for (int i = up; i; i >>= 1) {
if (bit[res | i] < vl && (res | i) <= tot) {
res |= i;
vl -= bit[res];
}
}
return res + 1;
}
inline int getpre(int vl) {return kth(query(vl - 1));}
inline int getnxt(int vl) {return kth(query(vl) + 1);}
int main() {
Read(n);
fu(i, 1, n) {
Read(op[i]);
Read(a[i]);
if (op[i] != 2) b[++tot] = a[i];
}
b[++tot] = -1;
sort(b + 1, b + tot + 1);
tot = unique(b + 1, b + tot + 1) - b - 1;
b[tot + 1] = -1;
fu(i, 1, tot) lowbit[i] = i & (-i);
while (up <= tot) up <<= 1; up >>= 1;
fu(i, 1, n) {
if (op[i] != 2) a[i] = lower_bound(b + 1, b + tot + 1, a[i]) - b;
switch (op[i]) {
case 0:insert(a[i]);break;
case 1:del(a[i]);break;
case 2:Write(b[kth(a[i])]);putchar('\n');break;
case 3:Write(query(a[i] - 1));putchar('\n');break;
case 4:Write(b[getpre(a[i])]);putchar('\n');break;
case 5:Write(b[getnxt(a[i])]);putchar('\n');break;
}
}
return 0;
}

LOJ107. 维护全序集【树状数组维护全序集】的更多相关文章

  1. [poj3378] Crazy Thairs (DP + 树状数组维护 + 高精度)

    树状数组维护DP + 高精度 Description These days, Sempr is crazed on one problem named Crazy Thair. Given N (1 ...

  2. HDU 5869 Different GCD Subarray Query (GCD种类预处理+树状数组维护)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5869 问你l~r之间的连续序列的gcd种类. 首先固定右端点,预处理gcd不同尽量靠右的位置(此时gc ...

  3. POJ 3321 Apple Tree(后根遍历将树转化成序列,用树状数组维护)

    题意:一棵树,有很多分叉,每个分叉上最多有1个苹果. 给出n,接下来n-1行,每行u,v,表示分叉u,v之间有树枝相连.这里数据中u相当于树中的父节点,v相当于子节点. 给出两个操作: 1.C x  ...

  4. 【Hihocoder 1167】 高等理论计算机科学 (树链的交,线段树或树状数组维护区间和)

    [题意] 时间限制:20000ms 单点时限:1000ms 内存限制:256MB 描述 少女幽香这几天正在学习高等理论计算机科学,然而她什么也没有学会,非常痛苦.所以她出去晃了一晃,做起了一些没什么意 ...

  5. 第十二届湖南省赛G - Parenthesis (树状数组维护)

    Bobo has a balanced parenthesis sequence P=p 1 p 2…p n of length n and q questions. The i-th questio ...

  6. 【BZOJ2124】等差子序列 树状数组维护hash值

    [BZOJ2124]等差子序列 Description 给一个1到N的排列{Ai},询问是否存在1<=p1<p2<p3<p4<p5<…<pLen<=N ...

  7. ACM-ICPC 2018 徐州赛区网络预赛 G. Trace【树状数组维护区间最大值】

    任意门:https://nanti.jisuanke.com/t/31459 There's a beach in the first quadrant. And from time to time, ...

  8. Playrix Codescapes Cup (Codeforces Round #413, rated, Div. 1 + Div. 2) C. Fountains 【树状数组维护区间最大值】

    题目传送门:http://codeforces.com/contest/799/problem/C C. Fountains time limit per test 2 seconds memory ...

  9. 2018中国大学生程序设计竞赛 - 网络选拔赛 1010 YJJ's Salesman 【离散化+树状数组维护区间最大值】

    题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6447 YJJ's Salesman Time Limit: 4000/2000 MS (Java/O ...

随机推荐

  1. HTML之实现页面缓存

    一般来说,对于html页面,一个站点,每个页面都会有相同的公共文件,比如页面的头部.尾部.侧边栏目.公共JS等.访问站点下的每一个页面,相同的公共文件,都需要重复从服务器下载.从性能和带宽角度看,重复 ...

  2. WPF应用的一些小总结(模板、样式,上下文)

    1: 后台:XXX.DataContext = ViewModel(数据对象)(XXX可以是当前的UserControl.Windows.Grid.TextBlock.Lable等UI控件,选择不同的 ...

  3. WPF:自定义ListBox的选择样式

    首先介绍一种简单地方法:就是通过自定义SystemColors类的参数来自定义WPF ListBox选择颜色的, SystemColors的HighlightBrushKey和HighlightTex ...

  4. 15 个有趣的 JS 和 CSS 库

    开发者们,一起来看看有木有你需要的前端库. 1. DisplayJS DisplayJS 是一个帮助你渲染 DOM 的简易框架.使用它,你可以更容易地将 JS 变量遍历到特定的 HTML 元素中,类似 ...

  5. Codeforces Round #378 (Div. 2)F - Drivers Dissatisfaction GNU

    http://codeforces.com/contest/733/problem/F 题意:给你一些城市和一些路,每条路有不满意程度和每减少一点不满意程度的花费,给出最大花费,要求找出花费小于s的最 ...

  6. SPOJ MYQ10 (数位DP)

    题意 询问区间[a,b]中的Mirror Number的个数,其中Mirror Number是指把它横着翻转后还能表示同样的数字. 思路 注意这个可不是回文数..除了0,1,8,别的数字翻转过后就不是 ...

  7. css3之calc()

    初识calc() 在使用calc()之前,我也只是听说有这么一个东西,但在用过之后我才发现这个功能其实很实用. calc()其实就是英文calculate(计算)的缩写,它看起来像个函数吧? 其实不是 ...

  8. .Net使用Redis详解之ServiceStack.Redis(7)

    Net使用Redis详解之ServiceStack.Redis(七) 序言 本篇从.Net如何接入Reis开始,直至.Net对Redis的各种操作,为了方便学习与做为文档的查看,我做一遍注释展现,其中 ...

  9. MySQL Index Condition Pushdown

    Index Condition Pushdown (ICP)是MySQL 5.6 版本中的新特性,是一种在存储引擎层使用索引过滤数据的一种优化方式.[Index Condition Pushdown] ...

  10. JQuery iframe

    子页面获取父页面的元素 function colisetapTJ() { var tapid = $('div:contains("添加档案报送"):last', window.p ...