4923: [Lydsy1706月赛]K小值查询 平衡树 非旋转Treap
国际惯例的题面:
这种维护排序序列,严格大于的进行操作的题都很套路......
我们按照[0,k],(k,2k],(2k,inf)分类讨论一下就好。
显然第一个区间的不会变化,第二个区间的会被平移进第一个区间,第三个区间的相对大小不会变化。
于是我们直接把第二个区间拆了重构,一个一个插入第一个区间即可。因为每次这样做最少减半,所以每个元素只会被重构log次,复杂度nlog^2n。
这种按照值域分离区间的操作,非旋转treap实现起来是最简单的......
然而第一次写非旋转treap还是出了一点问题,注意它的插入是通过按照值域分裂,新建点,再进行两次合并实现的。直接插入复杂度不对。
另外区间值域存在重合的情况两个treap不能直接合并......
我写的判定size的版本复杂度好像不对(不如暴力快?),于是只好预先生成fix值。
代码:
#include<cstdio>
#include<algorithm>
#include<cstdlib>
const int maxn=1e5+1e2; typedef std::pair<int,int> pii;
__inline pii mp(const int &x,const int &y) { return std::make_pair(x,y); } int seq[maxn],sql;
int stk[maxn],top; struct Treap {
int lson[maxn],rson[maxn],lazy[maxn],val[maxn],siz[maxn],fix[maxn],cnt; inline void init(int n) {
for(int i=;i<=n;i++) fix[i] = i;
std::random_shuffle(fix+,fix++n);
}
inline void apply(int pos,int x) {
if(pos) lazy[pos] += x , val[pos] -= x;
}
inline void push(int pos) {
if( lazy[pos] ) apply(lson[pos],lazy[pos]) , apply(rson[pos],lazy[pos]) , lazy[pos] = ;
}
inline void maintain(int pos) {
siz[pos] = siz[lson[pos]] + siz[rson[pos]] + ;
} inline pii split(int pos,int dv) { // left is <= , right is > .
if( !pos ) return mp(,);
push(pos);
if( dv < val[pos] ) {
pii spl = split(lson[pos],dv);
lson[pos] = spl.second , maintain(pos);
return mp(spl.first,pos);
} else {
pii spr = split(rson[pos],dv);
rson[pos] = spr.first , maintain(pos);
return mp(pos,spr.second);
}
}
inline int merge(int x,int y) {
if( !x || !y ) return x | y;
push(x) , push(y);
if( val[x] > val[y] ) std::swap(x,y);
if( fix[x] > fix[y] ) { // siz[x] is bigger .
lson[y] = merge(lson[y],x) , maintain(y);
return y;
} else {
rson[x] = merge(rson[x],y) , maintain(x);
return x;
}
}
inline void dfs(int pos) {
if( !pos ) return;
seq[++sql] = val[pos] , push(pos);
dfs(lson[pos]) , dfs(rson[pos]);
lson[pos] = rson[pos] = siz[pos] = , stk[++top] = pos;
}
inline int kth(int pos,int k) { // return the kth value .
if( k == siz[lson[pos]] + ) return val[pos];
return push(pos) , k <= siz[lson[pos]] ? kth(lson[pos],k) : kth(rson[pos],k-siz[lson[pos]]-);
}
inline void insert(int &root,int x) {
val[++cnt] = x , siz[cnt] = ;
pii sp = split(root,x);
root = merge(sp.first,cnt) , root = merge(root,sp.second);
}
inline void reinsert(int &root,int x) {
int cur = stk[top--];
val[cur] = x , siz[cur] = ;
pii sp = split(root,x);
root = merge(sp.first,cur) , root = merge(root,sp.second);
} }tp; int main() {
static int n,m,root,rtl,rtm,rtr;
scanf("%d%d",&n,&m) , tp.init(n);
for(int i=,t;i<=n;i++) scanf("%d",&t) , tp.insert(root,t);
for(int i=,o,x;i<=m;i++) {
scanf("%d%d",&o,&x);
if( o == ) printf("%d\n",tp.kth(root,x));
else if( o == ) {
pii sp = tp.split(root,x);
rtl = sp.first , sp = tp.split(sp.second,x<<);
rtm = sp.first , rtr = sp.second;
sql = , tp.dfs(rtm) , tp.apply(rtr,x);
for(int i=;i<=sql;i++) tp.reinsert(rtl,seq[i]-x);
root = tp.merge(rtl,rtr);
}
}
return ;
}
Thupc被拒了好气啊!我们队可是有yzy大爷的!(即使这样都被拒了,一看就是我太菜了)
ありのままでいればいつも
只要坚守自我维持现状
あるべき私かここにいると
自己希望成为的样貌就存在于此
信じてまた 新しい夢を
不要放弃希望 崭新的梦想
精一杯描き出せばいい
再次奋力地去描绘就好
そう気づき始めたよ私
是啊 而我开始意识到
みんなとただ笑ってる未来を
大家单纯地绽放笑容的未来
夢見て
诚心盼望
4923: [Lydsy1706月赛]K小值查询 平衡树 非旋转Treap的更多相关文章
- BZOJ 4923: [Lydsy1706月赛]K小值查询 Splay + 思维
Description 维护一个长度为n的正整数序列a_1,a_2,...,a_n,支持以下两种操作: 1 k,将序列a从小到大排序,输出a_k的值. 2 k,将所有严格大于k的数a_i减去k. In ...
- [BZOJ 4923][Lydsy1706月赛]K小值查询
传送门 势能分析平衡树,splay或treap都可以 放个指针版的就跑 #include <bits/stdc++.h> using namespace std; #define rep( ...
- [BZ4923][Lydsy1706月赛]K小值查询
K小值查询 题面 维护一个长度为n的正整数序列a_1,a_2,...,a_n,支持以下两种操作: 1 k,将序列a从小到大排序,输出a_k的值. 2 k,将所有严格大于k的数a_i减去k. Input ...
- BZOJ4923:[Lydsy1706月赛]K小值查询(Splay)
Description 维护一个长度为n的正整数序列a_1,a_2,...,a_n,支持以下两种操作: 1 k,将序列a从小到大排序,输出a_k的值. 2 k,将所有严格大于k的数a_i减去k. In ...
- BZOJ4923 [Lydsy1706月赛]K小值查询
题意 维护一个长度为n的正整数序列a_1,a_2,...,a_n,支持以下两种操作: 1 k,将序列a从小到大排序,输出a_k的值. 2 k,将所有严格大于k的数a_i减去k. \(n \leq 10 ...
- BZOJ3224普通平衡树——非旋转treap
题目: 此为平衡树系列第一道:普通平衡树您需要写一种数据结构,来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数, ...
- BZOJ3223文艺平衡树——非旋转treap
此为平衡树系列第二道:文艺平衡树您需要写一种数据结构,来维护一个有序数列,其中需要提供以下操作: 翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 ...
- [bzoj3065] 带插入区间第k小值 [重量平衡树套线段树]
题面 传送门 思路 发现强制在线了...... 本来可以树套树解决的问题,现在外层不能使用线段树了,拿什么替代呢? 我们需要一种支持单点插入.下套数据结构.数据结构上传合并复杂度最多单log,不能旋转 ...
- [bzoj4923]K小值查询
来自FallDream的博客,未经允许,请勿转载,谢谢. 维护一个长度为n的正整数序列a_1,a_2,...,a_n,支持以下两种操作: 1 k,将序列a从小到大排序,输出a_k的值. 2 k,将所有 ...
随机推荐
- Tomcat中catalina run后台运行脚本
编写启动脚本start.sh,将其放在/srv/aubapp/bin/下 #!/bin/sh #设置web应用程序目录 export CATALINA_BASE="/srv/aubapp&q ...
- 解决报错error the @annotation pointcut expression is only supported at Java 5
eclipse搭建环境后报错 error the @annotation pointcut expression is only supported at Java 5 错误意思大致是:注释切入点表达 ...
- GitHub学习一-本地电脑与GitHub绑定
1.创建ssh key $ ssh-keygen -t rsa -C "your_email@youremail.com"安装完git,右键git bash here,创建ssh ...
- Day6------------硬盘分区
1.sda1 sd:串行接口 a:第一块硬盘 1:第一个分区 ls /dev/sd 查看硬盘 fdisk -l /dev/sda 查看分区信息 block------------>8*512 8 ...
- SQL数据库基础知识
- C++ code:函数指针数组
函数指针作为一种数据类型,当然可以作为数组的元素类型.例如,要实现用菜单来驱动函数调用的程序框架,则用函数指针数组来实现就比较容易维护. #include<iostream> using ...
- linux 安装软件
apt-get install softname /安装软件apt-get update 是更新 /etc/apt/sources.list 和 /etc/apt/sources.list.d 中列出 ...
- laravel 同数据表字段比较查询和状态不正规排序
今天写群组推荐接口,要求未满的群 ( 群最大人数字段maxusers, 群人数字段affiliations_count 都在群组表中),官方,热门(普通群0 ,官方1,热门2 ) 排序的群 同表字段比 ...
- 步步为营-17-FileStream-文件加密/解密
以前使用的File是操作小的文本文件,用的并不常见,FileStream(操作字节),可以操作所有格式的文件,用途较广泛 下面做一个通过文件流给文件加密解密的小软件. using System; us ...
- DOM事件监听器
DOM事件监听器,允许一个事件触发多个方法.在实际工作中应用比较多. 它的调用形式如下: <body> <div> DOM事件监听器,允许一个事件触发多个方法. </di ...