(neng了好久好久才糊弄懂得知识点...) 一.李超线段树 在线动态维护一个二维平面直角坐标系, 支持插入一条线段, 询问与直线x = x0相交的所有线段中,交点y的最大/小值 (若有多条线段符合条件,输出编号最小的线段的编号) 洛谷板子题-Segment[HEOI2013]-洛谷T4097 二.add操作 整个李超线段树的核心就是add操作 1.特判 l == r 已经到了一个点 如果该点之前没有维护线段,直接维护现在的线段 如果该点已经维护过,选择纵坐标靠上的直线(点),纵坐标相同,选择编…
传送门 给出一个二维平面,给出若干根线段,求出x" role="presentation" style="position: relative;">xx坐标为x0" role="presentation" style="position: relative;">x0x0时在最上方的线段的标号(若有多条输出最小的). 线段树好题,这题是李超线段树板子题. 没学过的这道题可以让你很好的理解李超线段树…
题面 传送门 题解 调得咱自闭了-- 不难发现这就是个李超线段树,不过因为这里加入的是线段而不是直线,所以得把线段在线段树上对应区间内拆开之后再执行李超线段树的操作,那么复杂度就是\(O(n\log^2n)\) 以上是题解,以下是吐(zang)槽(hua) 为什么我插入竖直线段的时候会出现\(l=r\)且\(l\times k+b\neq r\times k+b\)的情况呢--为什么我本地测会突然\(RE\)加了个\(puts("qwq")\)就能输出了呢-- //minamoto #…
题目大意:维护一个二维平面,给定若干条线段,支持询问任意整数横坐标处对应的纵坐标最靠上的线段的 id,相同高度取 id 值较小的,强制在线. 题解:初步学习了李超线段树.李超线段树的核心思想在于通过标记永久化的方式来维护斜率. 代码如下 #include <bits/stdc++.h> using namespace std; const int maxn=1e5+10; const double eps=1e-6; inline int read(){ int x=0,f=1;char ch…
[BZOJ3165][HEOI2013]Segment(李超线段树) 题面 BZOJ 洛谷 题解 似乎还是模板题QwQ #include<iostream> #include<cstdio> #include<cmath> using namespace std; #define MAX 100100 #define lson (now<<1) #define rson (now<<1|1) inline int read() { int x=0…
题目链接 \(Click\) \(Here\) 李超线段树的模板.但是因为我实在太\(Naive\)了,想象不到实现方法. 看代码就能懂的东西,放在这里用于复习. #include <bits/stdc++.h> using namespace std; const int N = 100010; #define ls (p << 1) #define rs (p << 1 | 1) #define mid ((l + r) >> 1) struct Nod…
题意 题目链接 Sol 这题细节好多啊qwq..稍不留神写出一个小bug就要调1h+.. 思路就不多说了,把询问区间拆成两段就是李超线段树板子题了. 关于dis的问题可以直接维护. // luogu-judger-enable-o2 /* 李超线段树板子题 */ #include<bits/stdc++.h> #define Pair pair<int, int> #define MP(x, y) make_pair(x, y) #define fi first #define s…
题意 题目链接 Sol 李超线段树板子题.具体原理就不讲了. 一开始自己yy着写差点写自闭都快把叉积搬出来了... 后来看了下litble的写法才发现原来可以写的这么清晰简洁Orz #include<bits/stdc++.h> #define pdd pair<double, double> #define MP make_pair #define fi first #define se second using namespace std; const int MAXN = 1…
题面 传送门 题解 如果我们把路径拆成两段,那么这个路径加可以看成是一个一次函数 具体来说,设\(dis_u\)表示节点\(u\)到根节点的距离,那么\((x,lca)\)这条路径上每个节点的权值就会加上\(-dis_ua+dis_xa+b\),而\((lca,y)\)这条路径上每个节点就会加上\(dis_ua+a(dis_x+2\times dis_{lca})+b\) 区间加一次函数并维护最值,就是李超线段树啦~~~~ 我们把它给树剖了,那么同一条重链里\(dis\)肯定是递增的,我们就可以…
题面 传送门 题解 李超线段树板子 具体可以看这里 //minamoto #include<bits/stdc++.h> #define R register #define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i) #define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i) #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v…
所谓李超线段树就是解决此题一类的问题(线段覆盖查询点最大(小)),把原本计算几何的题目变成了简单的线段树,巧妙地结合了线段树的标记永久化与标记下传,在不考虑精度误差的影响下,打法应该是这样的. #include <cstdio> #include <cstring> #include <algorithm> #define mid(a,b) ((a+b)>>1) typedef long double ld; ; ; int cnt,sz; struct L…
题面传送门 首先一眼二分答案,我们假设距离 \((i,j)\) 最近的 scarefrog 离它的距离为 \(mn_{i,j}\),那么当我们二分到 \(mid\) 时我们显然只能经过 \(mn_{i,j}\ge mid\) 的点,如果我们已经知道了 \(mn_{i,j}\),那么检验 \(mid\) 是否可行就是一遍 BFS 能搞定的事,于是我们的目标就是求出 \(mn_{i,j}\) 即可. 故下面就有两种做法,一种是我的乱搞做法,一种是正经的做法. 乱搞做法 这就是某个奇怪的人自己发明出来…
3165: [Heoi2013]Segment Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 368  Solved: 148[Submit][Status][Discuss] Description 要求在平面直角坐标系下维护两个操作: 1.在平面上加入一条线段.记第i条被插入的线段的标号为i. 2.给定一个数k,询问与直线 x = k相交的线段中,交点最靠上的线段的编号. Input 第一行一个整数n,表示共n 个操作. 接下来n行,每行第一…
题目大意: 要求在平面直角坐标系下维护两个操作: 1.在平面上加入一条线段.记第 i 条被插入的线段的标号为 i 2.给定一个数 k,询问与直线 x = k 相交的线段中,交点最靠上的线段的编号. 若有多条线段符合要求,输出编号最小的线段的编号 (省略输入以及在线操作的要求) 分析: 明显的线段树特征: 1.有固定的 区间长度,(<=39989) 2.插入元素支持合并,(一个线段可以拆成两段线段) 所以我们用线段树来做这道题. 线段树维护什么元素开始不太好想. 发现要求一个交点最靠上的线段的编号…
[BZOJ1568][JSOI2008]Blue Mary开公司(李超线段树) 题面 BZOJ 洛谷 题解 是模板题啊. #include<iostream> #include<cstdio> using namespace std; #define MAX 50050 #define lson (now<<1) #define rson (now<<1|1) int Q,n=50000;char ch[20]; struct Node{bool fl;do…
BZOJ 洛谷 每次在路径上加的数是个一次函数,容易看出是树剖+李超线段树维护函数最小值.所以其实依旧是模板题. 横坐标自然是取个确定的距离标准.取每个点到根节点的距离\(dis[i]\)作为\(i\)的横坐标好了,这样对于同一条重链,横坐标还是递增的. 令\(w=LCA(u,v)\).如果在\((u,v)\)路径上加入直线\(y=kx+b\): 对于在\(u\to w\)路径上的点,每个点\(i\)的横坐标就是\(dis_u-dis_i\),所以对于\(i\),\(y=k(dis_u-dis_…
线段树分裂 以某个键值为中点将线段树分裂成左右两部分,应该类似Treap的分裂吧(我菜不会Treap).一般应用于区间排序. 方法很简单,就是把分裂之后的两棵树的重复的\(\log\)个节点新建出来,单次时间复杂度严格\(O(\log n)\). 至于又有合并又有分裂的复杂度,蒟蒻一直不会比较有说服力的证明,直到看见SovietPower巨佬的题解 对于只有合并:合并两棵线段树的过程,是找到它们\(x\)个重合的节点的位置,并将它们合并,而对于不重合的节点会跳过. 注意到合并与分裂类似互逆过程,…
Codeforces 题面传送门 & 洛谷题面传送门 这是一道李超线段树的毒瘤题. 首先我们可以想到一个非常 trivial 的 DP:\(dp_{i,j}\)​ 表示前 \(i\)​ 个数划分成 \(j\)​ 段的最小代价,那么显然 \(dp_{i,j}=\min\limits_{l<i}\{dp_{l,j-1}+(i-l)·\max\limits_{t=l+1}^ia_t\}\),这样暴力 DP 是 \(n^2k\) 的,一脸过不去. 考虑优化,注意到这里涉及一个 \(\max\),注意…
Codeforces 题面传送门 & 洛谷题面传送门 个人感觉这题称不上毒瘤. 首先看到选一条路径之类的字眼可以轻松想到点分治,也就是我们每次取原树的重心 \(r\) 并将路径分为经过重心和不经过重心两类路径.对于第二类路径我们肯定可以在对 \(r\) 所有子树进一步分治的过程中将其变成第一类路径,因此我们只用考虑怎样计算第一类路径的贡献即可. 显然对于一条第一类路径 \(x\to y\),我们要将其拆成 \(x\to r\) 和 \(r\to y\) 两部分分别处理,考虑怎样合并这两部分的贡献…
题目链接:戳我 这相当于是一个李超线段树的模板qwqwq,题解就不多说了. 代码如下: #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define MAXN 500010 using namespace std; int n,m; int t[MAXN<<2]; char s[10]; double k[MAXN<<1],b[MAX…
题意:有n个人,每个人有一件衣服需要洗,可以自己手洗花费t时间,也可以用洗衣机洗,但是洗衣机只有一台,即每个时刻最多只能有·一个人用洗衣机洗衣服.现在给你每个人最早可以开始洗衣服的时间,问当洗衣机的洗衣时间分别为1, 2....t的时候洗完所有衣服的最短时间. 思路:首先容易想到我们先把所有人按照洗衣服的时间排序.我们发现,最终洗衣服时间的瓶颈肯定在于后面的人,所以我们考虑怎么使用洗衣机使得总的洗衣时间最短.首先最后一个人是一定要用洗衣机洗衣服的,因为洗衣机的洗衣服时间 <= t, 那么最后一个…
4515: [Sdoi2016]游戏 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 304  Solved: 129[Submit][Status][Discuss] Description Alice 和 Bob 在玩一个游戏. 游戏在一棵有 n 个点的树上进行.最初,每个点上都只有一个数字,那个数字是 123456789123456789. 有时,Alice 会选择一条从 s 到 t 的路径,在这条路径上的每一个点上都添加一个数字.对于路径上…
1568: [JSOI2008]Blue Mary开公司 Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 557  Solved: 192[Submit][Status][Discuss] Description Input 第一行 :一个整数N ,表示方案和询问的总数. 接下来N行,每行开头一个单词“Query”或“Project”. 若单词为Query,则后接一个整数T,表示Blue Mary询问第T天的最大收益. 若单词为Project,则后…
更新了基础部分 更新了\(lazytag\)标记的讲解 线段树 Segment Tree 今天来讲一下经典的线段树. 线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点. 简单的说,线段树是一种基于分治思想的数据结构,用来维护序列的区间特殊值,相对于树状数组,线段树可以做到更加通用,解决更多的区间问题. 性质 1.线段树的每一个节点都代表了一个区间 2.线段树是一棵二叉树,具有唯一的根节点,其中,根节点代表的是整个区间\([1,n]\) 3…
听说正解是啥 set启发式合并+维护凸包+二分 根本不会啊 , 只会 李超线段树合并 啦 ... 题意 给你一颗有 \(n\) 个点的树 , 每个节点有两个权值 \(a_i, b_i\) . 从 \(u\) 跳到 \(v\) 的代价是 \(a_u \times b_v\) . 你需要计算每个节点跳到叶子的最小代价 . \((n \le 10^5, -10^5 \le a_i, b_i \le 10^5)\) 题解 我们首先考虑一个很容易的 \(dp\) , 令 \(dp_i\) 为 \(i\)…
BZOJ UOJ 以时间\(t\)为横坐标,位置\(p\)为纵坐标建坐标系,那每个机器人就是一条\(0\sim INF\)的折线. 用李超线段树维护最大最小值.对于折线分成若干条线段依次插入即可. 最好还是离线对时间离散化. 麻烦在写出来.. 复杂度\(O(c\log^2m+q\log m)\)? 以后李超树改用struct写了...学了一种写法好方便... //66516kb 5156ms #include <cstdio> #include <cctype> #include…
\(JUMP\) 很容易写出转移柿子 \[f_i=\min_{p_j<p_i}\{(h_i-h_j)^2+f_j\}+w_i\] 把\(\min\)里面的东西展开一下 \[f_j=\min_{p_j<p_i}\{-2h_jh_i+h_j^2+f_j\}+h_i^2+w_i\] 里面的\(\min\)是一个一次函数 首先这是一个类似于区间查询的东西,我们可以用树状数组 里面查询的东西是一个最小值,也就是说我们要资瓷插入一次函数并求最小值,超哥线段树就行了 所以这其实是个树套树,不过树状数组套什么…
大致题意: 给出两个序列A,B,A初始为负无穷,B初始为0,有三种操作 1.在A上区间[u,v]上加一个等差数列,取与原本A序列的最大值. 2.在B上区间[u,v]上加一个等差数列. 3.给出一个点X,询问A[X]+B[X]的值. 学习一个李超线段树就ojbk了,对于每次加入的等差数列,可以转化为y=a*i+b的一条线段,用李超线段树维护所有线段 所覆盖的区间即可.数据范围比较大,线段树可以动态开点,也可以离散化. #include<cstdio> #include<iostream&g…
原文链接:线段树(Segment Tree) 1.概述 线段树,也叫区间树,是一个完全二叉树,它在各个节点保存一条线段(即“子数组”),因而常用于解决数列维护问题,基本能保证每个操作的复杂度为O(lgN). 线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点. 对于线段树中的每一个非叶子节点[a,b],它的左儿子表示的区间为[a,(a+b)/2],右儿子表示的区间为[(a+b)/2+1,b].因此线段树是平衡二叉树,最后的子节点数目为N,即…
题目大意 题解 这道题需要用到一种叫做李超线段树的东西.我对于李超线段树,是这样理解的: 给节点打下的标记不进行下传,而是仅仅在需要的时候进行下传,这就是所谓永久化标记. 对于这道题,借用一张图, 这张图解释的比较清楚了. 代码 #include <algorithm> #include <cctype> #include <cstdio> int read() { int x = 0, f = 1; char ch = getchar(); while (!isdig…