【模板】树套树(线段树套Splay)
如题,这是一个模板。。。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cctype> #define max(x, y) (x > y ? x : y)
#define min(x, y) (x < y ? x : y) inline void read(int & x)
{
x = ;
int k = ;
char c = getchar();
while (!isdigit(c))
if (c == '-') c = getchar(), k = -;
else c = getchar();
while (isdigit(c))
x = (x << ) + (x << ) + (c ^ ),
c = getchar();
x *= k;
} const int inf = ;
const int N = ;
int n, m, tot, l, r, x, y, z, opt, mxa = -;
int cnt[N], faz[N], val[N], siz[N], a[N], son[N][], root[N]; //=======================================================================
//Splay inline int Getson(int u) { return son[faz[u]][] == u; } inline void Pushup(int u) { siz[u] = siz[son[u][]] + siz[son[u][]] + cnt[u]; } inline int Getmin(int u) { while (son[u][]) u = son[u][]; return u; } inline int Getmax(int u) { while (son[u][]) u = son[u][]; return u; } inline int Getx(int rtid, int x)
{
int u = root[rtid], las = ;
while (u && val[las = u] != x)
if (x >= val[u]) u = son[u][];
else u = son[u][];
return u ? u : las;
} void Rotate(int u)
{
int y = faz[u], z = faz[y], ch = Getson(u);
int b = son[u][ch ^ ], d = Getson(y);
son[u][ch ^ ] = y, son[y][ch] = b;
faz[y] = u, faz[b] = y, faz[u] = z;
if (z) son[z][d] = u;
Pushup(y), Pushup(u);
} void Splay(int rtid, int u, int tar)
{
while (faz[u] != tar)
{
if (faz[faz[u]] != tar)
if (Getson(u) == Getson(faz[u])) Rotate(faz[u]);
else Rotate(u);
Rotate(u);
}
if (!tar) root[rtid] = u;
} inline void Insert(int rtid, int x)
{
int u = root[rtid], las = ;
if (!root[rtid])
{
root[rtid] = u = ++tot;
val[u] = x; siz[u] = cnt[u] = ;
faz[u] = son[u][] = son[u][] = ;
return;
}
while (true)
{
++siz[u];
if (x == val[u])
{
++cnt[u];
break;
}
las = u;
if (x > val[u]) u = son[u][];
else u = son[u][];
if (!u)
{
u = ++tot, val[u] = x, faz[u] = las,
son[las][x > val[las]] = u;
son[u][] = son[u][] = ,
siz[u] = cnt[u] = ;
break;
}
}
Splay(rtid, u, );
} inline void Delete(int rtid, int x)
{
int u = root[rtid];
while (u)
if (x == val[u])
{
Splay(rtid, u, );
if (cnt[u] > ) { --cnt[u], --siz[u]; return; }
if (!son[u][] || !son[u][])
{
root[rtid] = son[u][] | son[u][];
faz[root[rtid]] = ;
return;
}
int newrt = Getmin(son[u][]);
faz[son[u][]] = ,
faz[son[u][]] = newrt,
son[newrt][] = son[u][];
Splay(rtid, newrt, );
return;
}
else if (x > val[u]) u = son[u][];
else u = son[u][];
} inline int Getkth(int rtid, int k)
{
int u = root[rtid];
if (siz[u] < k) return -inf;
while (u)
if (siz[son[u][]] >= k) u = son[u][];
else if (siz[son[u][]] + cnt[u] < k) k -= siz[son[u][]] + cnt[u], u = son[u][];
else return val[u];
} inline int Getrank(int rtid, int x)
{
//-------------------·½·¨Ò»------------------------
//Wrong Answer
/* int u = Getx(rtid, x);
Splay(rtid, u, 0);
return siz[son[u][0]];
*/ //-------------------·½·¨¶þ------------------------
int sum = , u = root[rtid];
while (u)
if (x == val[u]) return sum + siz[son[u][]];
else if (x > val[u]) sum += siz[son[u][]] + cnt[u], u = son[u][];
else u = son[u][];
return sum;
} int Pre(int rtid, int x)
{
int u = Getx(rtid, x);
if (val[u] < x) return val[u];
Splay(rtid, u, );
return son[u][] == ? -inf : val[Getmax(son[u][])];
} int Suf(int rtid, int x)
{
int u = Getx(rtid, x);
if (val[u] > x) return val[u];
Splay(rtid, u, );
return son[u][] == ? inf : val[Getmin(son[u][])];
} //Splay End
//=======================================================================
//Segment tree Begin #define Root 1, 1, n
#define Lson u << 1, l, mid
#define Rson u << 1 | 1, mid + 1, r
#define ls (u << 1)
#define rs (u << 1 | 1)
#define mid (l + r >> 1)
#define MID (L + R >> 1) inline void Segins(int u, int l, int r, int p, int x)
{
Insert(u, x);
if (l == r) return;
if (p <= mid) Segins(Lson, p, x);
else Segins(Rson, p, x);
} inline void Segmdf(int u, int l, int r, int p, int x)
{
Delete(u, a[p]), Insert(u, x);
if (l == r) { a[p] = x; return; }
if (p <= mid) Segmdf(Lson, p, x);
else Segmdf(Rson, p, x);
} inline int Segrak(int u, int l, int r, int x, int y, int z)
{
if (l == x && r == y) return Getrank(u, z);
if (y <= mid) return Segrak(Lson, x, y, z);
if (x > mid) return Segrak(Rson, x, y, z);
return Segrak(Lson, x, mid, z) + Segrak(Rson, mid + , y, z);
} inline int Segpre(int u, int l, int r, int x, int y, int z)
{
if (l == x && r == y) return Pre(u, z);
if (y <= mid) return Segpre(Lson, x, y, z);
if (x > mid) return Segpre(Rson, x, y, z);
return max(Segpre(Lson, x, mid, z), Segpre(Rson, mid + , y, z));
} inline int Segsuf(int u, int l, int r, int x, int y, int z)
{
if (l == x && r == y) return Suf(u, z);
if (y <= mid) return Segsuf(Lson, x, y, z);
if (x > mid) return Segsuf(Rson, x, y, z);
return min(Segsuf(Lson, x, mid, z), Segsuf(Rson, mid + , y, z));
} inline int Segkth(int l, int r, int k)
{
int cur, L = , R = mxa + ;
while (L < R)
{
cur = Segrak(Root, l, r, MID);
if (cur < k) L = MID + ;
else R = MID;
}
return L - ;
} signed main()
{
read(n), read(m);
for (int i = ; i <= n; ++i)
{
read(a[i]);
Segins(Root, i, a[i]);
mxa = max(mxa, a[i]);
}
for (int i = ; i <= m; ++i)
{
read(opt);
if (opt == ) read(x), read(y), Segmdf(Root, x, y);
else
{
read(l), read(r), read(x);
if (opt == ) printf("%d\n", Segrak(Root, l, r, x) + );
if (opt == ) printf("%d\n", Segkth(l, r, x));
if (opt == ) printf("%d\n", Segpre(Root, l, r, x));
if (opt == ) printf("%d\n", Segsuf(Root, l, r, x));
}
}
return ;
}
【模板】树套树(线段树套Splay)的更多相关文章
- P3380 【模板】二逼平衡树(树套树)(线段树套平衡树)
P3380 [模板]二逼平衡树(树套树) 前置芝士 P3369 [模板]普通平衡树 线段树套平衡树 这里写的是线段树+splay(不吸氧竟然卡过了) 对线段树的每个节点都维护一颗平衡树 每次把给定区间 ...
- [bzoj3196][Tyvj1730]二逼平衡树_树套树_位置线段树套非旋转Treap/树状数组套主席树/权值线段树套位置线段树
二逼平衡树 bzoj-3196 Tyvj-1730 题目大意:请写出一个维护序列的数据结构支持:查询给定权值排名:查询区间k小值:单点修改:查询区间内定值前驱:查询区间内定值后继. 注释:$1\le ...
- BZOJ 3110 ZJOI 2013 K大数查询 树套树(权值线段树套区间线段树)
题目大意:有一些位置.这些位置上能够放若干个数字. 如今有两种操作. 1.在区间l到r上加入一个数字x 2.求出l到r上的第k大的数字是什么 思路:这样的题一看就是树套树,关键是怎么套,怎么写.(话说 ...
- BZOJ 3218(a + b Problem-二分图套值域线段树)
出这题的人是怎么想出来的…… 言归正传,这题是二分图套值域线段树. 首先经过 @Vfleaking的神奇建图后,把图拆成二分图, 不妨利用有向图最小割的性质建图(以前我一直以为最小割和边的方向无关,可 ...
- [BZOJ1146][CTSC2008]网络管理Network(二分+树链剖分+线段树套平衡树)
题意:树上单点修改,询问链上k大值. 思路: 1.DFS序+树状数组套主席树 首先按照套路,关于k大值的问题,肯定要上主席树,每个点维护一棵权值线段树记录它到根的信息. 关于询问,就是Que(u)+Q ...
- LuoguP3834 【模板】可持久化线段树 1(主席树)|| 离散化
题目:[模板]可持久化线段树 1(主席树) 不知道说啥. #include<cstdio> #include<cstring> #include<iostream> ...
- 有趣的线段树模板合集(线段树,最短/长路,单调栈,线段树合并,线段树分裂,树上差分,Tarjan-LCA,势能线段树,李超线段树)
线段树分裂 以某个键值为中点将线段树分裂成左右两部分,应该类似Treap的分裂吧(我菜不会Treap).一般应用于区间排序. 方法很简单,就是把分裂之后的两棵树的重复的\(\log\)个节点新建出来, ...
- HDU 2665.Kth number-可持久化线段树(无修改区间第K小)模板 (POJ 2104.K-th Number 、洛谷 P3834 【模板】可持久化线段树 1(主席树)只是输入格式不一样,其他几乎都一样的)
Kth number Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- POJ 2104 K-th Number && 洛谷 P3834 【模板】可持久化线段树 1(主席树)
我惊奇的发现这两道题一模一样 题目背景 这是个非常经典的主席树入门题——静态区间第K小 数据已经过加强,请使用主席树.同时请注意常数优化 题目描述 如题,给定N个整数构成的序列,将对于指定的闭区间查询 ...
- luogu3834 【模板】可持久化线段树1(主席树)
关键字:线段树 可持久化 线段树:当版本(即对应的原序列的区间[1,r])一定时,每个节点的left,right下标为值域,值为其对应的原序列区间[1,r]中元素大小在值域中的元素个数. 可持久化:新 ...
随机推荐
- Oracle学习2 视图 索引 sql编程 游标 存储过程 存储函数 触发器
---视图 ---视图的概念:视图就是提供一个查询的窗口,来操作数据库中的数据,不存储数据,数据在表中. ---一个由查询语句定义的虚拟表. ---查询语句创建表 create table emp a ...
- ES6入门教程---数值扩展和数组扩展
1.数值扩展 var num = 0b11; console.log(num);3 var num = 0o11;console.log(num);9 var num = 1.234; console ...
- struts2.5+框架使用通配符与动态方法
概述:struts2.5以后加强了安全性,下面就是安全配置引发的问题 通配符: 在学习struts框架时经常会使用到通配符调用方法,如下: <package name="usercru ...
- Netty(6)关闭
客户端: public static void main(String[] args) throws Exception { final SslContext sslCtx; if (SSL) { ...
- Net Core构建Angular4应用程序
在Visual Studio 2017中使用Asp.Net Core构建Angular4应用程序 前言 Visual Studio 2017已经发布了很久了.做为集成了Asp.Net Core 1 ...
- Linux 运维培训笔记
2018/01/05 权限管理:sudoers文件 KAIFA_ADMINS ALL=(OP1) KAIFACMD 用户(大写) ...
- 客户端rsyslog配置文件详解
客户端rsyslog配置文件详解 最近再开发一个rsyslog的接收服务端,支持udp,tcp和tls三种协议.所以去仔细研究了一下rsyslog.conf的配置文件,下面来详细说一下. 因为我这儿重 ...
- td 内容自动换行 table表格td设置宽度后文字太多自动换行
设置table 的 style="table-layout:fixed;" 然后设置td的 style="word-wrap:break-word;" 即可 ...
- 字符串在forEach方法里面可以使用include函数
今天在写项目的时候,发现了一个问题,使用forEach函数,arr数组里面的字符串可以调用include方法,我查阅了很多地方,string里面没有这个方法. 但是在forEach函数里面确实可以这样 ...
- pt-table-checksum和pt-table-sync
环境:系统bsd,标准安装,ports安装的mysql. 主172.16.21.126 从172.16.21.128vi /etc/rc.conf 添加 mysql_enable="YES& ...