非旋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 次操作 ...
随机推荐
- python numpy实现多次循环读取文件 等间隔过滤数据
numpy的np.fromfile会出现如下的问题,只能一次性读取文件的内容,不能追加读取,连续两次的np.fromfile读到的东西一样 如果数据文件太大(几个G或以上)不能一次性全读进去,需要追加 ...
- CentOS6.5_64bit下编译安装MySQL-5.6.23
转载请注明出处:http://blog.csdn.net/guoyjoe/article/details/44785511 ************************************** ...
- loarocks install loadcaffe 失败
loarocks install loadcaffe 失败 1.Error: Your user does not have write permissions in /home/zhangliang ...
- 零基础学python-3.7 还有一个程序 python读写文本
今天我们引入另外一个程序,文件的读写 我们先把简单的程序代码贴上.然后通过我们多次的改进.希望最后可以变成一个简单的文本编辑器 以下是我们最简单的代码: 'crudfile--读写文件' def re ...
- 小贝_mysql select连接查询
select连接查询 简要: 一.union联合查询 二.左右内连接 一.union联合查询 作用: 把2次或多次查询结果合并起来 具体: (表1查询结果) union (表2查询结果) 运行: 先算 ...
- systemd、upstart和system V
http://blog.csdn.net/kumu_linux/article/details/7653802 systemd是Linux下的一种init软件,由Lennart Poettering ...
- laravel 将数组转化成字符串 再把字符串转化成数组
这是在给阮少翔改代码的时候用的方法, 开始的数据用explored转化成数组不是想要的结果, 我就自己写了一个方法把有用的信息提取出来拼接成一个字符串, 再用explored将字符串转化成数组. ...
- Nginx详细的安装教程(linux)
转:https://blog.csdn.net/u013641234/article/details/73838472 Nginx作为一个web服务器,目前使用最多的就利用其负载均衡,本篇着重讲解的是 ...
- linux SPI驱动——简单的gpio模拟SPI驱动测试 (二)
1: /* 2: * Add by xuyonghong for duotin car radio fm 3: * Copyright (C) 2016-5-24 xuyonghong@duotin. ...
- windows命令大全(转载)
winver---------检查Windows版本 wmimgmt.msc打开Windows管理体系结构(wmi) wupdmgrWindows更新程序 w脚本Windows脚本宿主设置 write ...