非旋treap套线段树
BZOJ3065。
去年用pascal 块链过了。。
今年来试了试非旋treap大法 注定被块链完爆
代码留这。
第一份 :辣鸡的 垃圾回收做法 跑得极慢
#include <bits/stdc++.h>
#define M 70000
using namespace std;
struct W{int l,r,s,v,e;}a[];
struct O{int l,r,s,k;}b[];
int nex[],A[],n,m,rt,ans,l,r,x,k,t,c,T,d[]; char op[];
void CL(int u){
if (!u) return; --b[u].k;
if (!b[u].k) nex[u]=t,t=u;
}
void NEW(int &u){
int U=t; t=nex[t]; CL(u);
CL(b[U].l); CL(b[U].r);
b[U]=(O){b[u].l,b[u].r,b[u].s,};
u=U; ++b[b[u].l].k; ++b[b[u].r].k;
}
void add(int &u,int x,int p,int q,int X){
NEW(u); b[u].s+=X;
if (p<q)
if (x<=p+q>>) add(b[u].l,x,p,p+q>>,X);
else add(b[u].r,x,(p+q>>)+,q,X);
if (!b[u].s) {nex[u]=t; t=u; u=;}
}
void he(int &u,int v,int p,int q){
if (!v) return;
if (!u) {++b[u=v].k; return;}
NEW(u); b[u].s+=b[v].s;
he(b[u].l,b[v].l,p,p+q>>);
he(b[u].r,b[v].r,(p+q>>)+,q);
}
void up(int u){
a[u].s=a[a[u].l].s+a[a[u].r].s+;
CL(a[u].e); a[u].e=;
add(a[u].e,a[u].v,,M,);
he(a[u].e,a[a[u].l].e,,M);
he(a[u].e,a[a[u].r].e,,M);
}
void build(int &u,int p,int q){
if (p>q) return;
u=p+q>>; a[u].v=A[u];
build(a[u].l,p,u-);
build(a[u].r,u+,q);
up(u);
}
void split(int u,int k,int &l,int &r){
if (!k) {l=; r=u; return;}
if (k==a[u].s) {l=u; r=; return;}
if (k<=a[a[u].l].s) split(a[u].l,k,l,a[u].l),up(r=u);
else split(a[u].r,k-a[a[u].l].s-,a[u].r,r),up(l=u);
}
void join(int &u,int k){
if ((1ll+a[u].s)*rand()<=RAND_MAX){
int A,B; split(u,k,A,B);
a[T].l=A; a[T].r=B; up(u=T);
}else{
if (k<=a[a[u].l].s) join(a[u].l,k);
else join(a[u].r,k-a[a[u].l].s-);
add(a[u].e,a[T].v,,M,); ++a[u].s;
}
}
void mody(int u,int k){
if (a[a[u].l].s+==k)
r=a[u].v,a[u].v=l; else
if (k<=a[a[u].l].s) mody(a[u].l,k);
else mody(a[u].r,k-a[a[u].l].s-);
add(a[u].e,r,,M,-);
add(a[u].e,l,,M,);
}
void find(int u,int l,int r){
if (r<||l>a[u].s) return;
if (l<=&&a[u].s<=r) {d[++c]=a[u].e; return;}
if (l<=a[a[u].l].s+&&a[a[u].l].s<r)
add(d[],a[u].v,,M,);
find(a[u].l,l,r);
find(a[u].r,l-a[a[u].l].s-,r-a[a[u].l].s-);
}
int main(){
srand();
scanf("%d",&n);
for (int i=;i<=n;++i) scanf("%d",&A[i]);
for (int i=;i<;++i) nex[i]=i+;
t=; build(rt,,n); T=n;
scanf("%d",&m);
while (m--){
scanf("%s",op);
if (op[]=='Q'){
scanf("%d%d%d",&l,&r,&k);
l^=ans; r^=ans; k^=ans;
c=; find(rt,l,r);
l=; r=M; int tt=d[];
while (l<r){
x=;
for (int i=;i<=c;++i) x+=b[b[d[i]].l].s;
if (x<k){
l=(l+r>>)+; k-=x;
for (int i=;i<=c;++i) d[i]=b[d[i]].r;
}else{
r=l+r>>;
for (int i=;i<=c;++i) d[i]=b[d[i]].l;
}
}
CL(tt); d[]=;
printf("%d\n",ans=l);
}else
if (op[]=='M'){
scanf("%d%d",&k,&l);
l^=ans; k^=ans;
mody(rt,k);
}else{
scanf("%d%d",&l,&k);
l^=ans; k^=ans; --l;
++T; a[T].v=k;
join(rt,l);
}
}
return ;
}
奈奈
第二份:暴力回收,暴力合并,快了许多
#include <bits/stdc++.h>
#define M 70000
#define S 15000000
using namespace std;
int D[S],rt,t,d[],m,x,l,r,k,n,ans,Q; char OP;
struct O{int l,r,s,v,e;}a[];
struct U{int l,r,s;}b[S];
void cl(int &u){
if (!u) return;
cl(b[u].l); cl(b[u].r);
D[++t]=u; b[u].s=; u=;
}
void add(int &u,int p,int q,int x){
if (!u) u=D[t--]; ++b[u].s;
if (p!=q)
if (x<=p+q>>) add(b[u].l,p,p+q>>,x);
else add(b[u].r,(p+q>>)+,q,x);
}
void del(int &u,int p,int q,int x){
--b[u].s;
if (p!=q)
if (x<=p+q>>) del(b[u].l,p,p+q>>,x);
else del(b[u].r,(p+q>>)+,q,x);
if (!b[u].s) D[++t]=u,u=;
}
int he(int l,int r){
if (!l&&!r) return ;
int u=D[t--];
b[u].s=b[l].s+b[r].s;
b[u].l=he(b[l].l,b[r].l);
b[u].r=he(b[l].r,b[r].r);
return u;
}
void up(int u){
a[u].s=a[a[u].l].s+a[a[u].r].s+;
cl(a[u].e);
a[u].e=he(a[a[u].l].e,a[a[u].r].e);
add(a[u].e,,M,a[u].v);
}
void build(int &u,int p,int q){
if (p>q) return;
u=p+q>>;
build(a[u].l,p,u-);
build(a[u].r,u+,q);
up(u);
}
void find(int u,int l,int r){
if (r<||l>a[u].s) return;
if (l<=&&a[u].s<=r) {d[++m]=a[u].e; return;}
int i=a[a[u].l].s+;
if (l<=i&&i<=r)
add(d[],,M,a[u].v);
find(a[u].l,l,r);
find(a[u].r,l-i,r-i);
}
void mody(int u){
int i=a[a[u].l].s+;
if (i==k) l=a[u].v,a[u].v=r; else
if (k<i) mody(a[u].l);
else k-=i,mody(a[u].r);
del(a[u].e,,M,l);
add(a[u].e,,M,r);
}
void split(int u,int k,int &l,int &r){
if (!k) {l=,r=u; return;}
if (k==a[u].s) {l=u,r=; return;}
if (k<=a[a[u].l].s){
split(a[u].l,k,l,a[u].l); up(r=u);
}else{
split(a[u].r,k-a[a[u].l].s-,a[u].r,r); up(l=u);
}
}
void join(int &u){
if ((1ll+a[u].s)*rand()<=RAND_MAX){
int A,B; split(u,k,A,B);
a[n].l=A; a[n].r=B; up(u=n);
}else{
if (k<=a[a[u].l].s) join(a[u].l);
else k-=a[a[u].l].s+,join(a[u].r);
add(a[u].e,,M,a[n].v); ++a[u].s;
}
}
int main(){
srand();
scanf("%d",&n);
for (int i=;i<=n;++i) scanf("%d",&a[i].v);
for (int i=S-;i;--i) D[i]=++t;
build(rt,,n);
scanf("%d",&Q);
while (Q--){
scanf("\n%c",&OP);
if (OP=='Q'){
scanf("%d%d%d",&l,&r,&k);
l^=ans; r^=ans; k^=ans;
m=; find(rt,l,r);
l=; r=M; int tt=d[];
while (l<r){
x=;
for (int i=;i<=m;++i) x+=b[b[d[i]].l].s;
if (x<k){
l=(l+r>>)+; k-=x;
for (int i=;i<=m;++i) d[i]=b[d[i]].r;
}else{
r=l+r>>;
for (int i=;i<=m;++i) d[i]=b[d[i]].l;
}
}
cl(d[]=tt); printf("%d\n",ans=l);
}else
if (OP=='M'){
scanf("%d%d",&k,&r);
k^=ans; r^=ans;
mody(rt);
}else{
scanf("%d%d",&k,&x);
k^=ans; a[++n].v=x^ans;
--k; join(rt);
}
}
return ;
}
雲珠桜
非旋treap套线段树的更多相关文章
- [模板] 平衡树: Splay, 非旋Treap, 替罪羊树
简介 二叉搜索树, 可以维护一个集合/序列, 同时维护节点的 \(size\), 因此可以支持 insert(v), delete(v), kth(p,k), rank(v)等操作. 另外, prev ...
- 平衡树简单教程及模板(splay, 替罪羊树, 非旋treap)
原文链接https://www.cnblogs.com/zhouzhendong/p/Balanced-Binary-Tree.html 注意是简单教程,不是入门教程. splay 1. 旋转: 假设 ...
- BZOJ1901 ZOJ2112 线段树+treap (线段树套线段树)
BZOJ1901: 线段树套线段树做法: (外层线段树 里层动态开节点的权值线段树) 有一个小小的trick 可以省掉二分变成nlog^2n的 就是把查询的区间都取出来- logn个一起走- 2016 ...
- 2018.08.06 bzoj1500: [NOI2005]维修数列(非旋treap)
传送门 平衡树好题. 我仍然是用的fhqtreap,感觉速度还行. 维护也比线段树splay什么的写起来简单. %%%非旋treap大法好. 代码: #include<bits/stdc++.h ...
- 非旋Treap及其可持久化
平衡树这种东西,我只会splay.splay比较好理解,并且好打,操作方便. 我以前学过SBT,但并不是很理解,所以就忘了怎么打了. 许多用平衡树的问题其实可以用线段树来解决,我们真正打平衡树的时候一 ...
- 非旋 treap 结构体数组版(无指针)详解,有图有真相
非旋 $treap$ (FHQ treap)的简单入门 前置技能 建议在掌握普通 treap 以及 左偏堆(也就是可并堆)食用本blog 原理 以随机数维护平衡,使树高期望为logn级别, FHQ ...
- 2827: 千山鸟飞绝 非旋treap
国际惯例的题面:看起来很不可做的样子,我们先来整理一下题意吧.就是,维护每个点曾经拥有过的最大的两个属性值,支持把点的位置移动.我们用map对每个位置进行离散化,对每个位置建立一个平衡树.为了方便分离 ...
- 非旋Treap总结 : 快过Splay 好用过传统Treap
非旋$Treap$ 其高级名字叫$Fhq\ Treap$,既然叫$Treap$,它一定满足了$Treap$的性质(虽然可能来看这篇的人一定知道$Treap$,但我还是多说几句:$Fhp\ Treap$ ...
- 【bzoj4785】[Zjoi2017]树状数组 线段树套线段树
题目描述 漆黑的晚上,九条可怜躺在床上辗转反侧.难以入眠的她想起了若干年前她的一次悲惨的OI 比赛经历.那是一道基础的树状数组题.给出一个长度为 n 的数组 A,初始值都为 0,接下来进行 m 次操作 ...
随机推荐
- 指针初始化为NULL的作用
关于空指针NULL.野指针.通用指针,首先说一下什么是指针,只要明白了指针的含义,你就明白null的含义了. 假设 有语句 int a=10;那么编译器就在内存中开辟1个整型单元存放变量a,我们假设这 ...
- Android 学习之逐帧动画(Frame)
帧动画就是将一些列图片.依次播放. 利用肉眼的"视觉暂留"的原理,给用户的感觉是动画的错觉,逐帧动画的原理和早期的电影原理是一样的. a:须要定义逐帧动画,能够通过代码定义.也能够 ...
- TIP2
mktemp :建立暂存/临时文件 more to see 'man mktemp' 语 法 mktemp[选择参数] 功 能 mktemp 命令:用于建立暂存文件,提供给shell脚本安全的使用临时 ...
- LeetCode215:Kth Largest Element in an Array
Find the kth largest element in an unsorted array. Note that it is the kth largest element in the so ...
- 软考考点---CPU
软考考点---CPU 中央处理器(CPU,Central Processing Unit)是一块超大规模的集成电路,是一台计算机的运算核心(Core)和控制核心( Control Un ...
- vi 之行号操作---显示行号、跳到指定行
1.设置行号显示 esc ->:->set nu 2.跳到指定行 esc-> 123gg 3. 进入命令模式 ?一:在冒号下输入 vim vi 在命令模式中 使用 d(版本不同 使用 ...
- oracle指定访问某表或某视图
在oracle中,想创建一个账号,然后只能只读地访问指定的表,怎么搞? 一.为特定的表创建视图 创建视图的时候还可以加上过滤条件,连访问哪些数据都可以指定. create or replace vie ...
- EasyPusher手机直播图像旋转90度后画面重复的问题
本文转自:http://blog.csdn.net/holo_easydarwin/article/details/51147379 最初在做EasyPusher手机直播的时候遇到过一个问题:手机竖屏 ...
- 基于XML配置的Sping AOP详解
一.编写基本处理方法 package com.kang.sping.xml.aop; public class Math{ //加 public int add(int n1,int n2){ int ...
- final、finally、三个关键字的区别
一 final 如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承.因此一个类不能既被声明为 abstract的,又被声明为final的.将变量或方法声明为final,可以 ...