题目大意:有$5$种操作:

  1. $1\;l\;r\;k:$查询$k$在区间$[l,r]$内的排名
  2. $2\;l\;r\;k:$查询区间$[l,r]$内排名为$k$的值
  3. $3\;pos\;k:$把第$pos$为上的数值改为$k$
  4. $4\;l\;r\;k:$查询$k$在区间$[l,r]$内的前驱
  5. $5\;l\;r\;k:$查询$k$在区间$[l,r]$内的后继

题解:树套树,权值线段树套平衡树

卡点:$TLE$卡了一会(我好菜啊)

C++ Code:

#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cctype> //#define ONLINE_JUDGE
namespace __IO {
namespace R {
int x;
#ifdef ONLINE_JUDGE
#define M (1 << 24)
char op[M], *ch = op;
inline void begin() {
fread(op, 1, M, stdin);
}
inline int read() {
while (isspace(*ch)) ch++;
for (x = *ch & 15, ch++; isdigit(*ch); ch++) x = x * 10 + (*ch & 15);
return x;
}
#undef M
#else
int ch;
inline int read() {
ch = getchar();
while (isspace(ch)) ch = getchar();
for (x = ch & 15, ch = getchar(); isdigit(ch); ch = getchar()) x = x * 10 + (ch & 15);
return x;
}
#endif
} namespace W {
#ifdef ONLINE_JUDGE
#define M (1 << 24)
char op[M], *ch = op - 1;
inline void end() {
fwrite(op, 1, ch - op + 1, stdout);
}
inline void write(int x) {
if (x > 9) write(x / 10);
*++ch = x % 10 ^ 48;
}
#undef M
#else
inline void write(int x) {
if (x > 9) write(x / 10);
putchar(x % 10 ^ 48);
}
#endif
}
}
using __IO::R::read;
using __IO::W::write; #define maxn 50010
#define N (maxn * 50)
const int inf = 0x7fffffff, maxl = 0, maxr = 1e8; namespace Treap {
int lc[N], rc[N], V[N], pri[N], sz[N];
int res, idx, ta, tb, tmp; inline int nw(int x) {
V[++idx] = x, sz[idx] = 1, pri[idx] = rand();
return idx;
}
inline int update(int rt) {
sz[rt] = sz[lc[rt]] + sz[rc[rt]] + 1;
return rt;
} void split(int rt, int k, int &x, int &y) {
if (!rt) x = y = 0;
else {
if (V[rt] <= k) split(rc[rt], k, rc[rt], y), x = update(rt);
else split(lc[rt], k, x, lc[rt]), y = update(rt);
}
}
int merge(int x, int y) {
if (!x || !y) return x | y;
if (pri[x] < pri[y]) {rc[x] = merge(rc[x], y); return update(x);}
else {lc[y] = merge(x, lc[y]); return update(y);}
} void insert(int &rt, int x) {
if (!rt) rt = nw(x);
else {
split(rt, x, ta, tb);
rt = merge(ta, merge(nw(x), tb));
}
}
void erase(int &rt, int x) {
split(rt, x, ta, tb);
split(ta, x - 1, ta, tmp);
rt = merge(ta, tb);
}
int gtrnk(int &rt, int l, int r) {
split(rt, l - 1, ta, tb);
split(tb, r, tmp, tb);
res = sz[tmp];
rt = merge(ta, merge(tmp, tb));
return res;
}
} namespace SgT {
int lc[N], rc[N], rt[N], idx;
int root; int pos, num;
void __insert(int &rt, int l, int r) {
if (!rt) rt = ++idx;
Treap::insert(SgT::rt[rt], pos);
if (l == r) return ;
int mid = l + r >> 1;
if (num <= mid) __insert(lc[rt], l, mid);
else __insert(rc[rt], mid + 1, r);
}
void insert(int __pos, int __num) {
pos = __pos, num = __num;
__insert(root, maxl, maxr);
} void __erase(int rt, int l, int r) {
Treap::erase(SgT::rt[rt], pos);
if (l == r) return ;
int mid = l + r >> 1;
if (num <= mid) __erase(lc[rt], l, mid);
else __erase(rc[rt], mid + 1, r);
}
void erase(int __pos, int __num) {
pos = __pos, num = __num;
__erase(root, maxl, maxr);
} int L, R, val;
int __gtrnk(int rt, int l, int r) {
if (l == r) return 1;
int mid = l + r >> 1;
if (val <= mid) return __gtrnk(lc[rt], l, mid);
else return Treap::gtrnk(SgT::rt[lc[rt]], L, R) + __gtrnk(rc[rt], mid + 1, r);
}
int gtrnk(int __L, int __R, int __val) {
L = __L, R = __R, val = __val;
return __gtrnk(root, maxl, maxr);
} int __gtkth(int rt, int l, int r, int k) {
if (l == r) return l;
int mid = l + r >> 1, tmp = Treap::gtrnk(SgT::rt[lc[rt]], L, R);
if (tmp >= k) return __gtkth(lc[rt], l, mid, k);
else return __gtkth(rc[rt], mid + 1, r, k - tmp);
}
int gtkth(int __L, int __R, int k) {
L = __L, R = __R;
return __gtkth(root, maxl, maxr, k);
} int pre(int L, int R, int x) {
int k = gtrnk(L, R, x);
if (k == 1) {
#ifdef ONLINE_JUDGE
*++__IO::W::ch = '-';
#else
putchar('-');
#endif
return inf;
}
else return gtkth(L, R, k - 1);
}
int nxt(int L, int R, int x) {
int k = gtrnk(L, R, x + 1);
if (k > R - L + 1) return inf;
else return gtkth(L, R, k);
}
} int n, m, V[maxn];
int main() {
// freopen("LG3380.in", "r", stdin);
// freopen("LG3380.txt", "w", stdout);
#ifdef ONLINE_JUDGE
__IO::R::begin();
#endif
srand(20040826);
n = read(), m = read();
for (int i = 1; i <= n; i++) {
V[i] = read();
SgT::insert(i, V[i]);
}
while (m --> 0) {
int op = read(), l = read(), r = read(), k;
if (op != 3) k = read();
switch (op) {
case 1:
write(SgT::gtrnk(l, r, k));
#ifdef ONLINE_JUDGE
*++__IO::W::ch = '\n';
#else
putchar('\n');
#endif
break;
case 2:
write(SgT::gtkth(l, r, k));
#ifdef ONLINE_JUDGE
*++__IO::W::ch = '\n';
#else
putchar('\n');
#endif
break;
case 3:
SgT::erase(l, V[l]);
V[l] = r;
SgT::insert(l, V[l]);
break;
case 4:
write(SgT::pre(l, r, k));
#ifdef ONLINE_JUDGE
*++__IO::W::ch = '\n';
#else
putchar('\n');
#endif
break;
case 5:
write(SgT::nxt(l, r, k));
#ifdef ONLINE_JUDGE
*++__IO::W::ch = '\n';
#else
putchar('\n');
#endif
break;
}
}
#ifdef ONLINE_JUDGE
__IO::W::end();
#endif
return 0;
}

  

[洛谷P3380]【模板】二逼平衡树(树套树)的更多相关文章

  1. BZOJ3196 & 洛谷3380:二逼平衡树——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=3196 https://www.luogu.org/problemnew/show/P3380 (题 ...

  2. bzoj 3196 Tyvj 1730 二逼平衡树(线段树套名次树)

    3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1807  Solved: 772[Submit][Stat ...

  3. bzoj 3196/ Tyvj 1730 二逼平衡树 (线段树套平衡树)

    3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description ...

  4. BZOJ3196 二逼平衡树 ZKW线段树套vector(滑稽)

    我实在是不想再打一遍树状数组套替罪羊树了... 然后在普通平衡树瞎逛的时候找到了以前看过vector题解 于是我想:为啥不把平衡树换成vector呢??? 然后我又去学了一下ZKW线段树 就用ZKW线 ...

  5. BZOJ3196 二逼平衡树 【线段树套平衡树】

    题目 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名 2.查询区间内排名为k的值 3.修改某一位值上的数值 4.查询k在区间内的前驱(前驱 ...

  6. BZOJ 3196 Tyvj 1730 二逼平衡树:线段树套splay

    传送门 题意 给你一个长度为 $ n $ 有序数列 $ a $ ,进行 $ m $ 次操作,操作有如下几种: 查询 $ k $ 在区间 $ [l,r] $ 内的排名 查询区间 $ [l,r] $ 内排 ...

  7. 洛谷.3835.[模板]可持久化平衡树(fhq treap)

    题目链接 对每次Merge(),Split()时产生的节点都复制一份(其实和主席树一样).时间空间复杂度都为O(qlogq).(应该更大些 因为rand()?内存真的爆炸..) 对于无修改的操作实际上 ...

  8. bzoj 3196 Tyvj 1730 二逼平衡树【线段树 套 splay】

    四舍五入就是个暴力. 对于线段树的每个区间都开一棵按权值排序的splay 对于第二个操作,二分一下,每次查询mid的排名,复杂度 $ O(nlog(n)^{3}) $ 其余的操作都是$ O(nlog( ...

  9. [BZOJ3196] [Tyvj1730] 二逼平衡树(线段树 套 Splay)

    传送门 至少BZOJ过了,其他的直接弃. 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名 2.查询区间内排名为k的值 3.修改某一位值上的 ...

  10. 洛谷P3380 【模板】二逼平衡树(树套树)(线段树+树状数组)

    P3380 [模板]二逼平衡树(树套树) 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 查询k在区间内的排名 查询区间内排名为k的值 修改某一位值上的数 ...

随机推荐

  1. C#中创建二维数组,使用[][]和[,]的区别

    C#中,我们在创建二维数组的时候,一般使用arr[][]的形式,例如 int[][] aInt = new int[2][]; 但声明二维数组还有一种方法,是使用arr[,]的形式.两者有什么区别呢? ...

  2. 「题目代码」P1044~P1048(Java)

    P1044 谭浩强C语言(第三版)习题5.8 import java.util.*; import java.io.*; import java.math.BigInteger; public cla ...

  3. Kotlin的密封(Sealed)类:超强的枚举(KAD 28)

    作者:Antonio Leiva 时间:Jun 27, 2017 原文链接:https://antonioleiva.com/sealed-classes-kotlin/ Kotlin的封装类是Jav ...

  4. 韦大仙--python对文件操作 2--写入与修改

    请大家看一段代码: yesterday2是我之前上个帖子创建的文件,为了方便大家看清我把本来的代码复制到下面: coding=utf-8 f=open("yesterday2",& ...

  5. Python的包(Packages)

    包,Package,是一种Python模块的集合,从文件组织形式上看,包就是一个文件夹,里面放着各种模块(.py文件),也可以有子文件夹(子包).包名构建了一个Python模块的命名空间.比如,模块名 ...

  6. lintcode: Check Sum of Square Numbers

    Check Sum of Square Numbers Given a integer c, your task is to decide whether there're two integers ...

  7. 卡片游戏 (Throwing card away I,UVa10935)

    题目描述: 解题思路: 直接模拟 #include <iostream> using namespace std; ] ; int main(int argc, char *argv[]) ...

  8. 【未完】训练赛20190304:KMP+树状数组+线段树+优先队列

    头炸了啊,只做出L题,前两天刚看的Shawn zhou的博客学习的,幸亏看了啊,否则就爆零了,发现题目都是经典题,线段树,KMP,我都没看过,最近又在复习考研,真后悔大一大二没好好学习啊,得抽时间好好 ...

  9. Python3 下安装python-votesmart

    在python2下安装python-smart还比较容易,而python3中由于很多函数库的变化直接使用python setup.py install 命令来安装的话会导致错误,而导致错误的原因就是p ...

  10. 基于AdaBoost算法——世纪晟结合Haar-like特征训练人脸检测识别

      AdaBoost 算法是一种快速人脸检测算法,它将根据弱学习的反馈,适应性地调整假设的错误率,使在效率不降低的情况下,检测正确率得到了很大的提高.   系统在技术上的三个贡献: 1.用简单的Haa ...