BZOJ3196——二逼平衡树
1、题目大意:给你一个序列,有5种操作,都有什么呢。。。
1> 区间第k小 这个直接用二分+树套树做
2> 区间小于k的有多少 这个直接用树套树做
3> 单点修改 这个直接用树套树做
4> 区间内k的前驱 这个就是1和2操作的合并,就是查询k的排名,然后就是知道他的前驱的排名,然后第k小
5> 区间内k的后继 这个和4同理
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
struct Node{
Node *ch[2];
int num, cnt, v, r;
bool operator < (const Node& rhs) const{
return r < rhs.r;
}
inline int cmp(int x){
if(x == v) return -1;
if(x < v) return 0;
return 1;
}
inline void maintain(){
cnt = num;
if(ch[0]) cnt += ch[0] -> cnt;
if(ch[1]) cnt += ch[1] -> cnt;
return;
}
} ft[5000000], *root[400000];
int tot;
int a[100000];
inline void treap_rotate(Node* &o, int d){
Node *k = o -> ch[d ^ 1];
o -> ch[d ^ 1] = k -> ch[d];
k -> ch[d] = o;
o -> maintain();
k -> maintain();
o = k;
return;
}
inline void treap_insert(Node* &o, int value){
if(!o){
o = &ft[tot ++];
o -> ch[0] = o -> ch[1] = NULL;
o -> num = 1;
o -> v = value;
o -> r = rand();
}
else{
int d = o -> cmp(value);
if(d == -1){
o -> num ++;
}
else{
treap_insert(o -> ch[d], value);
if(o -> ch[d] > o) treap_rotate(o, d ^ 1);
}
}
o -> maintain();
}
inline void treap_remove(Node* &o, int value){
if(!o) return;
int d = o -> cmp(value);
if(d == -1){
if(o -> num > 1) o -> num --;
else if(!o -> ch[0]) o = o -> ch[1];
else if(!o -> ch[1]) o = o -> ch[0];
else{
int d2;
if(o -> ch[0] > o -> ch[1]) d2 = 1;
else d2 = 0;
treap_rotate(o, d2);
treap_remove(o -> ch[d2], value);
}
}
else{
treap_remove(o -> ch[d], value);
}
if(o) o -> maintain();
}
inline int treap_lessk(Node* &o, int k){
if(!o) return 0;
int d = o -> cmp(k);
if(d == -1){
int ret = o -> num;
if(o -> ch[0]) ret += o -> ch[0] -> cnt;
return ret;
}
else if(d == 0){
return treap_lessk(o -> ch[d], k);
}
else{
int ss = o -> num;
if(o -> ch[0]) ss += o -> ch[0] -> cnt;
return treap_lessk(o -> ch[d], k) + ss;
}
}
inline int treap_find(Node* &o, int k){
if(!o) return 0;
int d = o -> cmp(k);
if(d == -1) return o -> num;
else return treap_find(o -> ch[d], k);
}
inline int segment_tree_find(int l, int r, int o, int x, int y, int k){
if(x <= l && r <= y){
return treap_find(root[o], k);
}
int mid = (l + r) / 2;
int ret = 0;
if(x <= mid) ret += segment_tree_find(l, mid, 2 * o, x, y, k);
if(y > mid) ret += segment_tree_find(mid + 1, r, 2 * o + 1, x, y, k);
return ret;
}
inline void segment_tree_add(int l, int r, int o, int x, int value){
treap_remove(root[o], a[x]);
treap_insert(root[o], value);
if(l == r){
a[x] = value;
return;
}
int mid = (l + r) / 2;
if(x <= mid) segment_tree_add(l, mid, 2 * o, x, value);
else segment_tree_add(mid + 1, r, 2 * o + 1, x, value);
}
inline int segment_tree_query_lessk(int l, int r, int o, int x, int y, int k){
if(x <= l && r <= y){
return treap_lessk(root[o], k);
}
int mid = (l + r) / 2;
int ret = 0;
if(x <= mid) ret += segment_tree_query_lessk(l, mid, 2 * o, x, y, k);
if(y > mid) ret += segment_tree_query_lessk(mid + 1, r, 2 * o + 1, x, y, k);
return ret;
}
inline int segment_tree_query_NO_k(int l, int r, int o, int x, int y, int k, int n){
int L = 0, R = 100000000;
while(L < R){
int mid = (L + R) / 2;
if(segment_tree_query_lessk(1, n, 1, x, y, mid) < k) L = mid + 1;
else R = mid;
}
return L;
}
int main(){
int n, m;
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i ++){
int x;
scanf("%d", &x);
segment_tree_add(1, n, 1, i, x);
}
for(int i = 1; i <= m; i ++){
int op, x, y, z;
scanf("%d", &op);
if(op == 1){
scanf("%d%d%d", &x, &y, &z);
int ans = segment_tree_query_lessk(1, n, 1, x, y, z);
ans -= segment_tree_find(1, n, 1, x, y, z);
ans ++;
printf("%d\n", ans);
}
else if(op == 2){
scanf("%d%d%d", &x, &y, &z);
int ans = segment_tree_query_NO_k(1, n, 1, x, y, z, n);
printf("%d\n", ans);
}
else if(op == 3){
scanf("%d%d", &x, &y);
segment_tree_add(1, n, 1, x, y);
}
else if(op == 4){
scanf("%d%d%d", &x, &y, &z);
int k = segment_tree_query_lessk(1, n, 1, x, y, z);
k -= segment_tree_find(1, n, 1, x, y, z);
int ans = segment_tree_query_NO_k(1, n, 1, x, y, k, n);
printf("%d\n", ans);
}
else{
scanf("%d%d%d", &x, &y, &z);
int k = segment_tree_query_lessk(1, n, 1, x, y, z);
k ++;
int ans = segment_tree_query_NO_k(1, n, 1, x, y, k, n);
printf("%d\n", ans);
}
}
return 0;
}
BZOJ3196——二逼平衡树的更多相关文章
- BZOJ3196二逼平衡树——线段树套平衡树(treap)
此为平衡树系列最后一道:二逼平衡树您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询 ...
- bzoj3196 二逼平衡树 树状数组套线段树
题目传送门 思路:树状数组套线段树模板题. 什么是树状数组套线段树,普通的树状数组每个点都是一个权值,而这里的树状数组每个点都是一颗权值线段树,我们用前缀差分的方法求得每个区间的各种信息, 其实关键就 ...
- bzoj3196 二逼平衡树 树套树(线段树套Treap)
Tyvj 1730 二逼平衡树 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 4697 Solved: 1798[Submit][Status][D ...
- bzoj3196 二逼平衡树
题目链接 平衡树系列最后一题 坑啊 10s时间限制跑了9764ms...还是要学一学bit套主席树啦... 经典的线段树套treap...至于第一发为什么要TLE(我不会告诉你treap插入的时候忘了 ...
- BZOJ3196 二逼平衡树 ZKW线段树套vector(滑稽)
我实在是不想再打一遍树状数组套替罪羊树了... 然后在普通平衡树瞎逛的时候找到了以前看过vector题解 于是我想:为啥不把平衡树换成vector呢??? 然后我又去学了一下ZKW线段树 就用ZKW线 ...
- [BZOJ3196] 二逼平衡树 [权值线段树套位置平衡树]
题面 洛咕题面 思路 没错我就是要不走寻常路! 看看那些外层位置数据结构,必须二分的,$O(n\log^3 n)$的做法吧! 看看那些cdq分治/树状数组套线段树的,空间$O(n\log^2 n)$挤 ...
- BZOJ3196 二逼平衡树 【线段树套平衡树】
题目 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名 2.查询区间内排名为k的值 3.修改某一位值上的数值 4.查询k在区间内的前驱(前驱 ...
- luogu3380/bzoj3196 二逼平衡树 (树状数组套权值线段树)
带修改区间K大值 这题有很多做法,我的做法是树状数组套权值线段树,修改查询的时候都是按着树状数组的规则找出那log(n)个线段树根,然后一起往下做 时空都是$O(nlog^2n)$的(如果离散化了的话 ...
- BZOJ3196:二逼平衡树(线段树套Splay)
Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名 2.查询区间内排名为k的值 3.修改某一位值上的数值 4.查询k在 ...
随机推荐
- Docker入门教程(一)介绍
http://dockone.io/article/101 Docker入门教程(一)介绍 [编者的话]DockerOne组织翻译了Flux7的Docker入门教程,本文是系列入门教程的第一篇,介绍了 ...
- 多态 oc c++ 与oc category
多态是函数调用的动态绑定技术: c++动态绑定依赖于this指针与虚函数表. 虚函数表的排序规则: 1)虚函数按照其声明顺序放于表中. 2)父类的虚函数在子类的虚函数前面. 3)如果子类重写了父类的虚 ...
- 深入剖析z-index属性
一.z-index七阶层叠顺序表 1.层叠顺序的大小比较: background/border < 负z-index < block块状水平盒子 < float浮动盒子 < i ...
- Apache和Nginx配置支持苹果ATS方法
什么是ATS功能? ATS是iOS9和OS X El Capitan的一个新特性.开启该功能后,ATS对使用NSURLConnection, CFURL或NSURLSession 等APIs 进行的网 ...
- 比较详细Python正则表达式操作指南(re使用)
比较详细Python正则表达式操作指南(re使用) Python 自1.5版本起增加了re 模块,它提供 Perl 风格的正则表达式模式.Python 1.5之前版本则是通过 regex 模块提供 E ...
- pickle模块简单使用
import pickle with open("school_info","wb") as school: user_input = str(input(&q ...
- ASP.NET技巧:教你制做Web实时进度条
网上已经有很多Web进度条的例子,但是很多都是估算时间,不能正真反应任务的真实进度.我自己结合多线程和ShowModalDialog制做了 一个实时进度条,原理很简单:使用线程开始长时间的任务,定义一 ...
- javascript模块简单写法
写法1: (function (wd, doc) { var mw = {}; mw.noConflict = noConflict; var _$ = wd.$; wd.$ = mw; functi ...
- Spring--Spring容器
在使用Spring所提供的各种丰富而神奇的功能之前,必须要在Spring IoC容器中装配好Bean,并建立Bean和Bean之间的关联关系. Spring提供了多种配置方式来实现Bean的装配.但在 ...
- Orchard源码分析(4.4):Orchard.Caching.CacheModule类
概述 CacheModule也是一个Autofac模块. 一.CacheModule类 CacheModule将DefaultCacheManager注册为ICacheManager: ...