[BZOJ3196] [Tyvj1730] 二逼平衡树(线段树 套 Splay)
至少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)的更多相关文章
- BZOJ3196 Tyvj1730 二逼平衡树 【树套树】 【线段树套treap】
BZOJ3196 Tyvj1730 二逼平衡树 Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名 2.查询区间内排名 ...
- 【BZOJ 3196】二逼平衡树 线段树套splay 模板题
我写的是线段树套splay,网上很多人写的都是套treap,然而本蒟蒻并不会treap 奉上sth神犇的模板: //bzoj3196 二逼平衡树,支持修改某个点的值,查询区间第k小值,查询区间某个值排 ...
- [bzoj3196][Tyvj1730]二逼平衡树_树套树_位置线段树套非旋转Treap/树状数组套主席树/权值线段树套位置线段树
二逼平衡树 bzoj-3196 Tyvj-1730 题目大意:请写出一个维护序列的数据结构支持:查询给定权值排名:查询区间k小值:单点修改:查询区间内定值前驱:查询区间内定值后继. 注释:$1\le ...
- BZOJ3196:二逼平衡树(线段树套Splay)
Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名 2.查询区间内排名为k的值 3.修改某一位值上的数值 4.查询k在 ...
- 【BZOJ-3196】二逼平衡树 线段树 + Splay (线段树套平衡树)
3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2271 Solved: 935[Submit][Stat ...
- BZOJ3196二逼平衡树——线段树套平衡树(treap)
此为平衡树系列最后一道:二逼平衡树您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询 ...
- bzoj 3196 && luogu 3380 JoyOI 1730 二逼平衡树 (线段树套Treap)
链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3196 题面; 3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Se ...
- BZOJ - 3196 Tyvj 1730 二逼平衡树 (线段树套treap)
题目链接 区间线段树套treap,空间复杂度$O(nlogn)$,时间复杂度除了查询区间k大是$O(log^3n)$以外都是$O(log^2n)$的. (据说线段树套线段树.树状数组套线段树也能过?) ...
- [bzoj3196]Tyvj 1730 二逼平衡树——线段树套平衡树
题目 Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名 2.查询区间内排名为k的值 3.修改某一位值上的数值 4.查 ...
- 【bzoj3196】Tyvj 1730 二逼平衡树 线段树套Treap
题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询k在区间内的前驱(前驱定义 ...
随机推荐
- B - Archer
Problem description SmallR is an archer. SmallR is taking a match of archer with Zanoes. They try to ...
- 2016/10/29 Action类中execute方法的使用
第一步:先配置web.xml文件 <filter> <filter-name>struts2</filter-name> <filter-class>o ...
- iOS生成PDF的关键代码-备忘
//此方法只是把当前页面的内容生成PDF并保存在沙盒中. //还需要做:把当前面没有显示的内容以分页的形式生成PDF,并把PDF读取并显示出来 //关于显示可以参考:念茜的博客 iOS开发笔记——PD ...
- $.extend(x,y); 函数用法介绍。
第一篇资料: 转自: https://www.cnblogs.com/yuqingfamily/p/5813650.html 语法:jQuery.extend( [deep ], target, o ...
- opencv4android移植到系统app
最近在尝试使用opencv4android实现投影仪的自动对焦功能,在AndroidStudio后需要将功能移到系统工程编译成系统app,仅以此文记录下移植过程中遇到的问题. 首先去opencv官网下 ...
- oracle 安装,启动 ,plsql 连接
1.下载oracle 服务器端,正常安装,在选择桌面类或者是服务器类的时候选择服务器类. 2.下载oracle 客户端解压版 下载地址 链接:https://pan.baidu.com/s/1mi ...
- 【数据分析 R语言实战】学习笔记 第三章 数据预处理 (下)
3.3缺失值处理 R中缺失值以NA表示,判断数据是否存在缺失值的函数有两个,最基本的函数是is.na()它可以应用于向量.数据框等多种对象,返回逻辑值. > attach(data) The f ...
- 关于js中使用close方法无法关闭firefox浏览器
今天遇到一个问题就是在js中使用window.close()方法无法关闭Firefox: 浏览器版本: firefox
- C# 获取文件编码
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Tex ...
- 使用GetLogicalDrives获取卷标
#include<stdio.h> #include<windows.h> int main() { DWORD dwLogical= GetLogicalDrives(); ...