传送门

至少BZOJ过了,其他的直接弃。

您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:

1.查询k在区间内的排名

2.查询区间内排名为k的值

3.修改某一位值上的数值

4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)

5.查询k在区间内的后继(后继定义为大于x,且最小的数)

最外层套一颗线段树,用来表示区间,线段树下面套个splay用来维护当前线段树节点的区间。

对于第二问可以二分,看看哪个数的排名为 k。

——代码

 #include <iostream>
#include <cstring>
#include <cstdio>
#define root 1, 1, n
#define lson now << 1, l, mid
#define rson now << 1 | 1, mid + 1, r
#define ls son[now][0]
#define rs son[now][1]
#define debug puts("**************"); const int MAXN = , INF = ; int n, m, sz;
int seq[MAXN], rt[MAXN];
int f[MAXN], son[MAXN][], cnt[MAXN], key[MAXN], size[MAXN]; inline int read()
{
int f = , x = ;
char ch = getchar();
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -;
for(; isdigit(ch); ch = getchar()) x = (x << ) + (x << ) + ch - '';
return x * f;
} inline int max(int x, int y)
{
return x > y ? x : y;
} inline int min(int x, int y)
{
return x < y ? x : y;
} inline void Splay_clear(int now)
{
f[now] = cnt[now] = key[now] = size[now] = ls = rs = ;
} inline void Splay_update(int now)
{
if(now)
{
size[now] = cnt[now];
if(ls) size[now] += size[ls];
if(rs) size[now] += size[rs];
}
} inline int Splay_get(int x)
{
return son[f[x]][] == x;
} inline void Splay_rotate(int x)
{
int old = f[x], oldf = f[old], wh = Splay_get(x); son[old][wh] = son[x][wh ^ ];
f[son[old][wh]] = old; son[x][wh ^ ] = old;
f[old] = x; if(oldf) son[oldf][son[oldf][] == old] = x;
f[x] = oldf; Splay_update(old);
Splay_update(x);
} inline void Splay_splay(int x)
{
for(int fa; fa = f[x]; Splay_rotate(x))
if(f[fa])
Splay_rotate(Splay_get(x) ^ Splay_get(fa) ? x : fa);
} inline void Splay_insert(int x, int k)
{
int now = rt[x], fa = ;
if(!rt[x])
{
rt[x] = ++sz;
key[sz] = k;
size[sz] = cnt[sz] = ;
return;
}
while()
{
if(k == key[now])
{
cnt[now]++;
Splay_update(now);
Splay_splay(now);
rt[x] = now;
return;
}
fa = now;
now = son[now][k > key[now]];
if(!now)
{
rt[x] = ++sz;
f[sz] = fa;
key[sz] = k;
size[sz] = cnt[sz] = ;
son[fa][k > key[fa]] = sz;
//Splay_update(fa);
Splay_splay(sz);
return;
}
}
} inline int Splay_findrank(int x, int k)
{
int now = rt[x], ans = ;
while()
{
if(!now) return ans;
if(key[now] == k) return ans + size[ls];
else if(key[now] < k)
{
ans += cnt[now] + size[ls];
now = rs;
}
else now = ls;
}
} inline int Splay_find(int x, int k)
{
int now = rt[x];
while()
{
if(key[now] > k) now = ls;
else if(key[now] < k) now = rs;
else
{
rt[x] = now;
Splay_splay(now);
return now;
}
}
} inline int Splay_pre(int x)
{
int now = son[rt[x]][];
while(rs) now = rs;
return now;
} inline int Splay_suc(int x)
{
int now = son[rt[x]][];
while(ls) now = ls;
return now;
} inline void Splay_del(int x)
{
int now = rt[x];
if(cnt[now] > )
{
cnt[now]--;
Splay_update(now);
return;
}
if(!ls && !rs)
{
rt[x] = ;
Splay_clear(now);
return;
}
if(!ls || !rs)
{
rt[x] = ls + rs;
f[rt[x]] = ;
Splay_clear(now);
return;
}
int pre = Splay_pre(x);
Splay_splay(pre);
rt[x] = pre;
son[pre][] = rs;
f[rs] = pre;
Splay_clear(now);
Splay_update(pre);
} inline int Splay_findpre(int x, int k)
{
int now = rt[x], ans = -INF;
while(now)
{
if(key[now] < k)
{
ans = max(ans, key[now]);
now = rs;
}
else now = ls;
}
return ans;
} inline int Splay_findsuc(int x, int k)
{
int now = rt[x], ans = INF;
while(now)
{
if(key[now] > k)
{
ans = min(ans, key[now]);
now = ls;
}
else now = rs;
}
return ans;
} inline void SegTree_insert(int x, int k, int now, int l, int r)
{
Splay_insert(now, k);
if(l == r) return;
int mid = (l + r) >> ;
if(x <= mid) SegTree_insert(x, k, lson);
else SegTree_insert(x, k, rson);
} inline int SegTree_askrank(int x, int y, int k, int now, int l, int r)
{
if(x <= l && r <= y) return Splay_findrank(now, k);
if(l > y || r < x) return ;
int mid = (l + r) >> ;
return SegTree_askrank(x, y, k, lson) + SegTree_askrank(x, y, k, rson);
} inline void SegTree_change(int x, int k, int now, int l, int r)
{
Splay_find(now, seq[x]);
Splay_del(now);
Splay_insert(now, k);
if(l == r) return;
int mid = (l + r) >> ;
if(x <= mid) SegTree_change(x, k, lson);
else SegTree_change(x, k, rson);
} inline int SegTree_findpre(int x, int y, int k, int now, int l, int r)
{
if(x <= l && r <= y) return Splay_findpre(now, k);
if(l > y || r < x) return -INF;
int mid = (l + r) >> ;
return max(SegTree_findpre(x, y, k, lson), SegTree_findpre(x, y, k, rson));
} inline int SegTree_findsuc(int x, int y, int k, int now, int l, int r)
{
if(x <= l && r <= y) return Splay_findsuc(now, k);
if(l > y || r < x) return INF;
int mid = (l + r) >> ;
return min(SegTree_findsuc(x, y, k, lson), SegTree_findsuc(x, y, k, rson));
} int main()
{
int i, opt, x, y, z, ans, h, t, mid, maxn = ;
n = read();
m = read();
for(i = ; i <= n; i++) seq[i] = read(), maxn = max(maxn, seq[i]), SegTree_insert(i, seq[i], root);
for(i = ; i <= m; i++)
{
opt = read();
switch(opt)
{
case :
{
x = read();
y = read();
z = read();
printf("%d\n", SegTree_askrank(x, y, z, root) + );
break;
}
case :
{
x = read();
y = read();
z = read();
h = , t = maxn;
while(h <= t)
{
mid = (h + t) >> ;
if(SegTree_askrank(x, y, mid, root) + <= z) h = mid + ;
else ans = mid, t = mid - ;
}
printf("%d\n", ans - );
break;
}
case :
{
x = read();
z = read();
SegTree_change(x, z, root);
seq[x] = z;
maxn = max(maxn, z);
break;
}
case :
{
x = read();
y = read();
z = read();
printf("%d\n", SegTree_findpre(x, y, z, root));
break;
}
case :
{
x = read();
y = read();
z = read();
printf("%d\n", SegTree_findsuc(x, y, z, root));
break;
}
}
}
return ;
}

[BZOJ3196] [Tyvj1730] 二逼平衡树(线段树 套 Splay)的更多相关文章

  1. BZOJ3196 Tyvj1730 二逼平衡树 【树套树】 【线段树套treap】

    BZOJ3196 Tyvj1730 二逼平衡树 Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名 2.查询区间内排名 ...

  2. 【BZOJ 3196】二逼平衡树 线段树套splay 模板题

    我写的是线段树套splay,网上很多人写的都是套treap,然而本蒟蒻并不会treap 奉上sth神犇的模板: //bzoj3196 二逼平衡树,支持修改某个点的值,查询区间第k小值,查询区间某个值排 ...

  3. [bzoj3196][Tyvj1730]二逼平衡树_树套树_位置线段树套非旋转Treap/树状数组套主席树/权值线段树套位置线段树

    二逼平衡树 bzoj-3196 Tyvj-1730 题目大意:请写出一个维护序列的数据结构支持:查询给定权值排名:查询区间k小值:单点修改:查询区间内定值前驱:查询区间内定值后继. 注释:$1\le ...

  4. BZOJ3196:二逼平衡树(线段树套Splay)

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

  5. 【BZOJ-3196】二逼平衡树 线段树 + Splay (线段树套平衡树)

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

  6. BZOJ3196二逼平衡树——线段树套平衡树(treap)

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

  7. bzoj 3196 && luogu 3380 JoyOI 1730 二逼平衡树 (线段树套Treap)

    链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3196 题面; 3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Se ...

  8. BZOJ - 3196 Tyvj 1730 二逼平衡树 (线段树套treap)

    题目链接 区间线段树套treap,空间复杂度$O(nlogn)$,时间复杂度除了查询区间k大是$O(log^3n)$以外都是$O(log^2n)$的. (据说线段树套线段树.树状数组套线段树也能过?) ...

  9. [bzoj3196]Tyvj 1730 二逼平衡树——线段树套平衡树

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

  10. 【bzoj3196】Tyvj 1730 二逼平衡树 线段树套Treap

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

随机推荐

  1. 选择排序 分类: 算法 c/c++ 2014-10-10 20:32 509人阅读 评论(0) 收藏

    选择排序(假设递增排序) 每次选取从当前结点到末尾结点中最小的一个与当前结点交换,每一轮固定一个元素位置. 时间复杂度O(n^2),空间复杂度O(1).下面的示例代码以带头结点的链表为存储结构: #i ...

  2. jmeter(十五)Jmeter默认报告优化

    一.本文目的: 之前写了两篇文章搭建持续集成接口测试平台(Jenkins+Ant+Jmeter)和ANT批量执行Jmeter脚本,功能实现上都没有什么问题,但是最后生成的报告有一点小问题,虽然不影响使 ...

  3. 怎么将ts文件快速合成一个文件

    ts文件的排序要有一定的规则,最简单的就是:1.ts.2.ts.3.ts等.   使用Win + R打开下面窗口.   输入“cmd”,点击“确定”,打开下面窗口.   输入命令行:“copy /b ...

  4. 每天学点linux命令之locate 与 find 命令

    定位某个文件的位置 方法一 sudo find / -name libGLEW.so.1.13 -type f 方法二 sudo updatedb && locate libopenc ...

  5. 在windows下用python调用darknet的yolo接口

    0,目标 本人计算机环境:windows7 64位,安装了vs2015专业版,python3.5.2,cygwin,opencv3.3,无gpu 希望实现用python调用yolo函数,实现物体检测. ...

  6. 数组(Arry)几个常用方法的详解

    join() 方法用于把数组中的所有元素放入一个字符串.元素是通过指定的分隔符进行分隔的. arrayObject.join(separator)separator 可选.指定要使用的分隔符.如果省略 ...

  7. vue2.0 路由传参(router-link传过去)

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  8. 中国版 Office 365 (X-Tenant / Tango) 功能验证报告 - 2 基本步骤

    说明: 1. 前期准备 - 在Azure上模拟出生产环境: 包括父域域控.子域域控.父域的Exchange Server.子域的Exchange Server.对Exchange Server, 需要 ...

  9. base64记载

    一丶 js /** * * Base64 encode / decode * * @author haitao.tu * @date 2010-04-26 * @email tuhaitao@foxm ...

  10. PHP 下基于 php-amqp 扩展的 RabbitMQ 简单用例 (二) -- Topic Exchange 和 Fanout Exchange

    Topic Exchange 此模式下交换机,在推送消息时, 会根据消息的主题词和队列的主题词决定将消息推送到哪个队列. 交换机只会为 Queue 分发符合其指定的主题的消息. 向交换机发送消息时,消 ...