【模板】树套树(线段树套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]中元素大小在值域中的元素个数. 可持久化:新 ...
随机推荐
- 笔记-JavaWeb学习之旅14
JSTL:JavaServer Pages Tag Library JSP标准标签库 if标签 <%@ page import="java.util.ArrayList" % ...
- python基本数据类型2——操作
字符串 name = "alex" # 移除两边的空格 print(name.strip()) #strip不修改值 # 是否以"al"开头 print(nam ...
- 监控数组与foreach绑定-Knockout.js
html: <h2>Your seat reservations</h2> <table> <thead> <tr> ...
- PostgreSQL 导出导入表中指定查询数据
创建一临时表: create table test_view as select * from test where date(to_timestamp(endtime))>='2012-09- ...
- 低版本Firefox支持innerText属性兼容方法
FireFox支持innerText属性了,很遗憾是44.0.2版本以下还需要兼容处理. 方法一: innerHTML是符合W3C标准的属性,而innerText只适用于IE浏览器,因此,尽可能地去使 ...
- JFrame Frame 窗口关闭
JFrame是Frame的子类,即JFrame继承自Frame. JFrame是javax.swing.JFrame的类,Frame是java.awt.Frame的类. 类似的还有JButton.Bu ...
- Spring的七种事务传播机制
概述 当我们调用一个基于Spring的Service接口方法(如UserService#addUser())时,它将运行于Spring管理的事务环境中,Service接口方法可能会在内部调用其它的Se ...
- mongodb的投影
mongodb 投影意思是只选择必要的数据而不是选择一个文件的数据的整个.如果一个文档有5个字段,需要显示只有3个,然后选择其中只有3个字段. find() 方法 MongoDB 的find()方法, ...
- 公司项目git开发流程规范
手动修改冲突之后,git add . git commit ,git push
- Elasticsearch-基本操作2
Elasticsearch版本:6.0 为了避免并发修改的冲突问题,数据库中,经常用悲观锁和乐观锁来控制并发问题,而Elasticsearch使用乐观锁.如果源数据在读写过程中被修改,更新将失败,应用 ...