题目描述

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

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

维护一个多重集 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. idea 快捷键及使用技巧

    IDEA中经常使用的快捷键: Ctrl+Shift + Enter 语句完成 可以快速在行末添加分号,或添加大括号{} Ctrl+Shift + F 全文查找 需要把搜狗打字的快捷键关掉 Ctrl+A ...

  2. try throw catch typeid

    QString str = ui.ll->text(); try { if (str == NULL) { throw 1; } else { throw 1.2; } } catch (int ...

  3. 数据可视化——matplotlib(2)

    导入相关模块 import matplotlib.pyplot as plt import numpy as np import pandas as pd 图表设置 添加X.Y轴标签以及图标标题 a ...

  4. mvn deploy返回400错误的几种可能

    user credentials are wrong url to server is wrong user does not have access to the deployment reposi ...

  5. 完美解决 No toolchains found in the NDK toolchains folder for ABI with prefix: mips64el-linux-android

    问题描述 好久之前的一个Android项目,最近需要重构一下 因为Android Studio的开发环境以及Gradle的版本等等都进行了一定的更新,于是导入Project以后,出现了报错: No t ...

  6. 关于 Token,你应该知道的十件事

    转自:http://ju.outofmemory.cn/entry/134189 原文是一篇很好的讲述 Token 在 Web 应用中使用的文章,而这是我和 Special 合作翻译的译文. 1. T ...

  7. Hibernate中"二级缓存"配置

    实体类 : package cn.happy.entity; public class Emp { private Integer empNo; private String empName; pub ...

  8. 安装使用babel-polyfill。让IE支持es6

    安装 npm install --save-dev babel-polyfill 使用 在你的代码头部加载babel-polyfill,注意一定要在你的代码开始前,第一个js文件的顶部.如果是vue在 ...

  9. 009——数组(九) each list array_map array_walk array_walk_recursive

    <?php /** * 9 数组 each list array_map array_walk array_walk_recursive */ //each() 返回数组中的键名和键值生成新数组 ...

  10. EasyUI Combobox 组合框

    默认选择第一项,加请选择,取值问题 <input class="easyui-combobox" id="ddlWHS" name="ddlWH ...