李超树

它本质上是线段树的拓展运用

解决的问题:平面直角坐标系中,支持插入线段,问 \(x = x_0\) 这条直线上最大的 \(y\) 值

它维护的东西很奇特:优势线段

何为“优势线段”?

给定两条线在指定区间内,所有 \(x\) 对应的两个 \(y\) 高的数量越多的就是优势线段

如下

蓝线便是优势线段

我们在线段树对应的本区间就维护蓝线的斜率和截距就行了

不过红线不能就此抛弃,而应让它下放到它可能具有优势的区间

这样的话,我们需要把询问所在的区间跑完才能弄出答案

因为正确答案可能已经被下放到了比较靠下的地方,即更小的区间

以上是大致思路,具体过程如下

  1. 此刻区间里面还没有维护的东西,那么直接更新线段树信息即可
  2. 新线段与此刻线段树维护的线段没有交点,如果新线段在线段树维护的线段树之上,那么直接更新,否则 \(return\)
  3. 新线段与此刻线段树维护的线段有交点,那么就需要分类讨论了。
当交点的 \(x\) 轴坐标在区间正中心的左侧时,如果新线段的斜率高于原线段,那么很明显线段树维护的值就要变成新线段了(上面的图就是这种情况),但在变成新线段之前要把原线段的信息下放到左子树(即交点所在的半个原区间)。若斜率低于原线段,那么本区间的优势线段没有变,就直接递归讨论线段树的左儿子即可。右侧同理,具体见例题代码。

最好自己手划一下,然后打一遍标程,再对一遍标程就会板了

时间复杂度:插入直线时,每次将直线的定义域分隔到 \(\log n\) 个区间,每个区间最多把标记下传 \(\log n\) 层,因此修改的时间复杂度为 \(\log(n^2)\)。(但常数不大)

总的复杂度是:\(nlog(n^2)\)

例题:

思路分析:裸题,直接上李超树

注意:加的是线段!即区间加入一条线段而非直线

而题中只需维护 \([1..10^5]\) 中线段的信息就行了

板子

\(Code\)

#include<cstdio>
using namespace std; const int N = 1e5 + 5;
int n , m , fl[4 * N]; struct tree{
long double k , b;
}seg[4 * N]; inline void swap(int &x , int &y){int t = x; x = y , y = t;}
inline long double max(long double x , long double y){return x < y ? y : x;}
inline long double min(long double x , long double y){return x < y ? x : y;}
inline long double Intersection(long double k1 , long double b1 , long double k2 , long double b2){return 1.0 * (b2 - b1) / (k1 - k2);} inline void update(long double k , long double b , int x , int y , int l , int r , int rt)
{
if (y < l || x > r) return;
int mid = (l + r) >> 1;
if (l >= x && r <= y)
{
if (!fl[rt])
{
seg[rt].b = b , seg[rt].k = k , fl[rt] = 1;
return;
}
long double f1 = seg[rt].k * l + seg[rt].b , f2 = seg[rt].k * r + seg[rt].b;
long double f3 = k * l + b , f4 = k * r + b;
if (f1 >= f3 && f2 >= f4) return;
else if (f1 <= f3 && f2 <= f4) seg[rt].k = k , seg[rt].b = b;
else{
long double len = Intersection(k , b , seg[rt].k , seg[rt].b);
if (f1 <= f3)
{
if (len <= mid) update(k , b , x , y , l , mid , rt << 1);
else update(seg[rt].k , seg[rt].b , x , y , mid + 1 , r , rt << 1 | 1) , seg[rt].k = k , seg[rt].b = b;
}
else{
if (len > mid) update(k , b , x , y , mid + 1 , r , rt << 1 | 1);
else update(seg[rt].k , seg[rt].b , x , y , l , mid , rt << 1) , seg[rt].k = k , seg[rt].b = b;
}
}
return;
}
if (x <= mid) update(k , b , x , y , l , mid , rt << 1);
if (y > mid) update(k , b , x , y , mid + 1 , r , rt << 1 | 1);
} inline long double query(int l , int r , int rt , int x)
{
long double ans = 1.0 * x * seg[rt].k + seg[rt].b;
if (l == r) return ans;
int mid = (l + r) >> 1;
if (x <= mid) ans = max(ans , query(l , mid , rt << 1 , x));
else ans = max(ans , query(mid + 1 , r , rt << 1 | 1 , x));
return ans;
} int main()
{
freopen("query.in" , "r" , stdin);
freopen("query.out" , "w" , stdout);
scanf("%d%d" , &n , &m);
int x1 , x2 , y1 , y2;
long double k , b;
for(register int i = 1; i <= 4 * 1e5 + 1; i++) seg[i].b = -1e18 , seg[i].k = 0;
for(register int i = 1; i <= n; i++)
{
scanf("%d%d%d%d" , &x1 , &y1 , &x2 , &y2);
if (x1 > x2) swap(x1 , x2) , swap(y1 , y2);
if (x1 == x2) k = 0 , b = max(1.0 * y1 , 1.0 * y2);
else k = 1.0 * (y1 - y2) / (x1 - x2) , b = 1.0 * y1 - 1.0 * k * x1;
update(k , b , x1 , x2 , 1 , 1e5 , 1);
}
int opt;
while(m--)
{
scanf("%d" , &opt);
if (opt == 0)
{
scanf("%d%d%d%d" , &x1 , &y1 , &x2 , &y2);
if (x1 > x2) swap(x1 , x2) , swap(y1 , y2);
if (x1 == x2) k = 0 , b = max(1.0 * y1 , 1.0 * y2);
else k = 1.0 * (y1 - y2) / (x1 - x2) , b = 1.0 * y1 - 1.0 * k * x1;
update(k , b , x1 , x2 , 1 , 1e5 , 1);
}
else{
scanf("%d" , &opt);
long double ans = query(1 , 1e5 , 1 , opt);
printf("%.6Lf\n" , ans == -1e18 ? ans = 0 : ans);
}
}
}

李超树学习笔记 & JZOJ 5039. 【NOI2017模拟4.2】查询题解的更多相关文章

  1. zkw线段树学习笔记

    zkw线段树学习笔记 今天模拟赛线段树被卡常了,由于我自带常数 \(buff\),所以学了下zkw线段树. 平常的线段树无论是修改还是查询,都是从根开始递归找到区间的,而zkw线段树直接从叶子结点开始 ...

  2. 仙人掌&圆方树学习笔记

    仙人掌&圆方树学习笔记 1.仙人掌 圆方树用来干啥? --处理仙人掌的问题. 仙人掌是啥? (图片来自于\(BZOJ1023\)) --也就是任意一条边只会出现在一个环里面. 当然,如果你的图 ...

  3. Java程序猿的JavaScript学习笔记(6——面向对象模拟)

    计划按例如以下顺序完毕这篇笔记: Java程序猿的JavaScript学习笔记(1--理念) Java程序猿的JavaScript学习笔记(2--属性复制和继承) Java程序猿的JavaScript ...

  4. Spring学习笔记(七)模拟实际开发过程的调用过程XML版-Setter方式注入

    模拟实际开发过程的调用过程XML版-Setter方式注入 源码获取github [TOC] 1.项目结构 2.jar包跟上个一样 3.重写set方法 UserServiceImpl.java 1234 ...

  5. 线段树学习笔记(基础&进阶)(一) | P3372 【模板】线段树 1 题解

    什么是线段树 线段树是一棵二叉树,每个结点存储需维护的信息,一般用于处理区间最值.区间和等问题. 线段树的用处 对编号连续的一些点进行修改或者统计操作,修改和统计的复杂度都是 O(log n). 基础 ...

  6. MySql学习笔记(一)之DQL常用查询

    MySql学习笔记(一)之DQL常用查询 前言:mysql是中小型的数据库软件,SQL语言分为DDL,DCL,DML,DQL四种,在这里重点讲解DQL的单表查询. 正文:在学习mysql单表查询之前, ...

  7. JSOI2008 Blue Mary开公司 | 李超线段树学习笔记

    题目链接:戳我 这相当于是一个李超线段树的模板qwqwq,题解就不多说了. 代码如下: #include<iostream> #include<cstdio> #include ...

  8. Treap-平衡树学习笔记

    平衡树-Treap学习笔记 最近刚学了Treap 发现这种数据结构真的是--妙啊妙啊~~ 咳咳.... 所以发一发博客,也是为了加深蒟蒻自己的理解 顺便帮助一下各位小伙伴们 切入正题 Treap的结构 ...

  9. Dynamic CRM 2013学习笔记(十)客户端几种查询数据方式比较

    我们经常要在客户端进行数据查询,下面分别比较常用的几种查询方式:XMLHttpRequest, SDK.JQuery, SDK.Rest. XMLHttpRequest是最基本的调用方式,JQuery ...

  10. [原创]java WEB学习笔记19:初识MVC 设计模式:查询,删除 练习(理解思想),小结 ,问题

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...

随机推荐

  1. python3实现AES加密

    前言 这几天研究了一下 python 实现 AES 加密,有很多坑 AES 加密的参数及其条件 这个 AES 加密的主要坑就在于这些条件, 首先 aes 加密有一下几个参数 秘钥:加密的时候用秘钥,解 ...

  2. [HNCTF]Web详解_原创

    WEB Challenge__rce 根据给出的源代码来看典型的命令执行但是正则匹配掉说有的字母只留下数字和少量字符串. 根据大佬给出的思路使用自增绕过 <?php error_reportin ...

  3. 前端内容(HTML CSS javaScript)

    前端内容 前端基础之HTML 前端基础之HTML HTML标签使用 HTML之form表单 前端基础之CSS 前端基础之CSS CSS字体颜色 背景 盒子模型 CSS浮动 溢出 头像框 CSS定位 i ...

  4. Karmada多云多集群生产实践专场圆满落幕

    摘要:CNCF Karmada社区Cloud Native Days China 2022南京站成功举办. 本文分享自华为云社区<Karmada多云多集群生产实践专场圆满落幕|Cloud Nat ...

  5. 【Java面试指北】反射(1) 初识反射

    如果你被问到:什么是反射?为什么需要反射.以及反射的应用?你会如何回答呢? 本篇会带大家初识反射,了解反射概念和基本应用.反射的原理以及深入源码的探究将会在后面几篇介绍. 一.什么是反射? 要理解什么 ...

  6. linux挖矿处置

    挖矿的类型 主动挖矿:用户在个人电脑或服务器使用挖矿程序进行CPU,GPU计算,获取虚拟货币. 被动挖矿:挖矿病毒通过系统漏洞,恶意程序,弱口令等方式入侵服务器,设备感染挖矿病毒后会开始挖掘虚拟货币. ...

  7. 记一次在CentOS上安装GitLab的流程

    1.本次环境说明 系统:Centos7.6 IP地址:http://192.168.3.213: 最低配置要求:2核心CPU和4G内存,这是因为[GitLab]的整体运行包含了多个进程  2.自行安装 ...

  8. 巧用视觉障眼法,还原 3D 文字特效

    最近群里有这样一个有意思的问题,大家在讨论,使用 CSS 3D 能否实现如下所示的效果: 这里的核心难点在于,如何利用 CSS 实现一个立体的数字?CSS 能做到吗? 不是特别好实现,但是,如果仅仅只 ...

  9. [深度探索C++对象模型]关于成员初始化列表(member initiallization list)

    四种特殊情况: 1.当初始化一个reference member时. 2.当初始化一个const member时. 3.当初始化一个base class的constructor,而它拥有一组参数时. ...

  10. AtCoder Regular Contest 148 B - dp

    题面 For a string \(T\) of length \(L\) consisting of d and p, let \(f(T)\) be \(T\) rotated \(180\) d ...