闲话 9.29(更新了鲜花部分)

因为没有模拟赛,所以考虑捡捡之前漏下的小点。

// Upd:这样的标题看的人应该会多些? 更新了鲜花

注:LCA 之后的讲解中可能会出现一些自由的文字,酌情阅读。

Better Days

Run away, run away, yeah
Take your time to say a prayer
Recognize me when you sneak in
Don't be cruel, open up your heart and say
Ho-ho-ho-hold on, there will be better days
It'll be a better day
God, oh god, please help me
I need someone that can guide me
The right way, the right way
I don't need you to judge me
I just need someone to love me
The right way
We dream, we hope, we pray for better days
We dream, we hope, we pray for better days
Let it rain, let it rain
Every storm followed by a brighter day
Recognize love when you see it
Only you can open up your heart and say
Ho-ho-ho-hold on, there will be better days
There will be better days
God, oh god, please help me
I need someone that can guide me
The right way, the right way
I don't need you to judge me
I just need someone to love me
The right way
We dream, we hope, we pray for better days
We dream, we hope, we pray for better days
We dream, we hope, we pray for better days


dfs 序求 LCA

倍增 LCA 的常数还是过于大了,虽然好记但会导致我们在一些数据奇异的题中比其它方式求 LCA 的人的得分要低。

所以就有了这个用 dfs 序求 lca 的高科技,在时间效率和代码好写程度上都薄纱其它方法的狠活。

思路

建议画个简单图手模一下

设我们要求 \(u\)\(v\) 两点的 lca 为 \(d\),两点不重合,令 \(dfn_u\lt dfn_v\)

首先考虑 \(u\)\(v\) 之间不存在祖先关系的情况。此时 dfs 的顺序是从 \(d\)\(u\) 再回退到 \(d\) 再到 \(v\)。那么根据 dfs 的性质,任何 \(d\) 及其祖先的点均不会出现在 \(dfn_u\)\(dfn_v\) 这个范围内;再考虑 \(d\)\(v\) 方向的第一个子节点 \(x\),显然有 \(dfn_u\lt dfn_x\lt dfn_v\)。也就是说,我们只需要找出一个 dfs 序在上述范围内的深度最浅的点,其父节点就是我们所求的 \(d\)

再考虑二者存在祖先关系怎么处理。暴力判断虽然可行,但与我们这样做的目的就相悖了,我们要找到一个优雅的方式来求解。由 \(dfn_u\lt dfn_v\) 可知 \(u\)\(v\) 祖先,我们按上述方法寻找到的 \(x\)\(u\),显然与答案不符。所以我们考虑修改上述范围,将其改成 \(dfn_u+1\) ~\(dfn_v\) 即可。思考这样做在情况一的正确性,由于 \(u\) 显然不能成为我们要找的 \(x\),所以去掉该点不会对答案造成影响。

唯一的不足就是无法处理 \(u=v\) 的情况,特判一下即可。

实现

借助 ST 表来完成,预处理的复杂度是 \(\mathcal{O(n\log n)}\) 的,但常数小了很多。

模板题代码:

const int Ratio = 0;
const int N = 5e5 + 5;
int n, m, s;
namespace WLCA
{int dfn[N], tot, st[31][N], lg[N];int hh[N], to[N << 1], ne[N << 1], cnt;void Wadd(int u, int v){to[++cnt] = v, ne[cnt] = hh[u], hh[u] = cnt;}int Wget(int x, int y){return dfn[x] < dfn[y] ? x : y;}void Wdfs(int u, int fa){dfn[u] = ++tot, st[0][dfn[u]] = fa;for(int i = hh[u]; i != -1; i = ne[i]){int v = to[i];if(v == fa) continue;Wdfs(v, u);}}int Wlca(int x, int y){if(x == y) return x;if((x = dfn[x]) > (y = dfn[y])) swap(x, y);int d = lg[y - x++];return Wget(st[d][x], st[d][y - (1 << d) + 1]);}short main(){n = qr, m = qr, s = qr;memset(hh, -1, sizeof hh);for(int i = 1; i < n; i++){int a = qr, b = qr;Wadd(a, b), Wadd(b, a);}Wdfs(s, 0);for(int i = 2; i <= tot + 1; i++)lg[i] = lg[i >> 1] + 1;for(int i = 1; i <= lg[n]; i++)for(int j = 1; j + (1 << i) - 1 <= n; j++)st[i][j] = Wget(st[i - 1][j], st[i - 1][j + (1 << (i - 1))]);for(int i = 1; i <= m; i++){int a = qr, b = qr;printf("%d\n", Wlca(a, b));}return Ratio;}
}
  • 顶针教的,讲的比较好的是这篇博客,引用了部分内容。

建虚树

众所周知,点有五个,关键点有三个。

你说的不对,但是虚树有两种建法,一种是好写好理解复杂度不好的双 sort 建树,一种是不好写不好理解复杂度好的单调栈维护。但是题解不会顺着你的思路来,所以两种方法都要深度理解下。

双 sort 建树

思路

好理解,不写了。

其实理解它主要依赖于理解虚树到底要留哪些点。知道为什么留 lca 了就明白为什么这么建树了。

实现很简单,按 dfs 序 sort 一遍,开随便什么存一下每个点及相邻点的 lca,再 sort 一遍,再 unique 一遍,然后根据原树上关系加边就行了。

实现

好写,不写了。

int dfn[N], tot, a[N], b[N], m, len;
bool cmp(int a, int b){return dfn[a] < dfn[b];}
void Wbuild()
{sort(a + 1, a + m + 1, cmp);for(int i = 1; i < m; i++)b[++len] = a[i], b[++len] = Wlca(a[i], a[i + 1]);b[++len] = a[m];sort(b + 1, b + len + 1, cmp);len = unique(b + 1, b + len + 1) - b - 1;for(int i = 1; i < len; i++){int lca = Wlca(b[i], b[i + 1]);Wadd(lca, b[i + 1]);}
}

单调栈建树

5k:为什么要学单调栈建树?

Ratio:不是说这个跑得快点

5k:复杂度都是一样的,少的这点常数也不会去卡,再说了单调栈你还容易写挂,双 sort 就很难写挂

所以不写这个了。

差分约束

由于昨天晚上饭堂,导致写 D 时被迫复习了差分约束。

经过

具体的,开始先打了一遍本来能过的 dfs 做法,然后由于我觉得可能会爆 1e18 就很天才的给 i 赋了一个 \(\frac{max+min}{2}\),然后其它还有很多脑瘫的地方所以 WA + TLE 导致我觉得这种做法不可行然后怒吃 8 发罚时。

差分约束系统 是一种特殊的 \(n\) 元一次方程组,它包含……

嗯,这有啥好说的,还是挑重点吧。

给你若干个形如 \(x_i + x_j \le k\) 的限制,询问是否有符合上述所有限制的解。

思路

联想大法好:发现 \(x_i - x_j \le k\) 和求醉短路中的松弛操作 \(dis_v\lt dis_u +w_i\) 很像,因此我们将每一个数 \(x_i\) 都当做图中的一个点,每个约束看作由 \(x_j\)\(x_i\) 引一条长度为 \(k\) 的边。

如果符号是 \(\gt\) 你就两边同时乘上一个 \(-1\),如果是 \(=\) 你就看成两个限制 \(x_i-x_j\le k\)\(x_j-x_i\le -k\),连两条边就行了。至于其它的符号,本质上没啥区别,自己转化一下。

实现

公元 4202 年,智慧的人类掌握了复活已死的事物这一技术,并以 SPFA 为对象进行了秘密测试,结果未知。

采用 SPFA 算法,若跑出负环了显然是无解的情况,否则跑出的 \(dis_i\) 就是所有限制下的一组解。

由于限制是以差分形式存在的,所以若 \(a_1,a_2\cdots a_n\) 是符合题目要求的一组解,那么 \(a_1 + k,a_2+k\cdots a_n+k\) 也是符合要求的另一组解。由这个性质可以实现一些题目中对解的范围限制。

例题:无

啊不对,昨天晚上刚做了一道。

例题:有

Problem

谔谔虽然你们暴力都过了并且我的暴力改完也过了,但我赛时打的差分约束所以它就是模板题。

很好的条件,确保了一定有解,所以我们完全可以省掉判负环的步骤,直接开局建一个超级原点,按差分的性质连边,跑一遍就没了,因为 \(10^9\times 2\times 10^5\lt 10^{18}\),所以压根不用管题目的 \(x_i\le |10^{18}|\),初始值设成 0 肯定跑不炸。

Submitted code 这里放的现打的因为赛时太唐了做了一堆唐氏操作,喜欢唐人的可以自己去搜。

lower_bound 妙用

在 vp abc371 的时候想要差一个有序数组中第一个小于等于 \(x\) 的值的位置,但发现好像没有现成的函数直接用,于是学习了一下重载 lower_bound。

食用方法

首先,一般的 lower_bound 或 upper_bound 需要一个升序的数组,然后这样用。

lower_bound(begin, end, value);
upper_bound(begin, end, value);

这里 begin 和 end 是你想查询的数组边界范围的指针,value 是你想查询的第一个 不小于 / 大于 的数。

回忆可知优先队列的小根堆实现我们用了 greater<int> 函数,所以我们如果要实现一个支持查询 不大于 / 小于 一个数的函数,需要用 greater<int>() 重载。

首先你需要一个单调不上升的数组,然后这样用。

lower_bound(begin, end, value, greater<int>());
upper_bound(begin, end, value, greater<int>());

返回值的类型仍然是下标,然后就可以肆意操作了。

准备一个 例题,别的暴力方法可能能过,不过都学了这个了就考虑怎么用线段树做。

首先位置是严格递增给出的,所以不用去管 \(x_i\le |10^9|\) 的条件,直接维护一棵大小为 \(n\) 的线段树就行了。我们另开一个数组按降序存下标,查询时左边界取第一个不小于 \(L_i\) 的下标,有边界取第一个不大于 \(R_i\) 的下标即可。非常的好写啊。

鲜花

  • 1 能不能不要再逆天发言了,哦好像这几个字排列已经被你们发掘完了,怪不得没动静了

  • 2
    Ratio:jijidawang 你想说点什么吗
    jijidawang:我想说点什么吗

  • 3
    (jijidawang 在翻看上一届的模拟赛成绩)
    Ratio:看看最后一名是谁(yzh)
    顶针:yanzihe
    Ratio:哪个 yan
    顶针:yxc 的闫
    Ratio:为啥不是我这个颜
    顶针:你这个颜太少见了,上次见还是颜丑
    5k:颜丑是啥
    顶针:就三国那个文良颜丑
    5k:那不是颜良文丑吗
    顶针:哦,反正他俩老在一块
    5k:那 huge 和消费股还老在一块呢,你咋不喊朱晓飞
    顶针:你咋不倒着念小肥猪


完结撒花~

image

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/805879.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

南沙C++信奥赛陈老师解一本通题 1973:【16NOIP普及组】买铅笔

​【题目描述】P老师需要去商店买n支铅笔作为小朋友们参加NOIP的礼物。她发现商店一共有3种包装的铅笔,不同包装内的铅笔数量有可能不同,价格也有可能不同。为了公平起见,P老师决定只买同一种包装的铅笔。 商店不允许将铅笔的包装拆开,因此P老师可能需要购买超过n支铅笔才够…

城市空间设计对居民生活质量的影响:构建宜居城市的蓝图

在快节奏的现代生活中,城市不仅是经济活动的中心,更是人们生活、工作、休闲的综合载体。本文旨在深入探讨城市空间设计如何通过科学规划、人性化考量以及生态融合,为居民打造更加宜居、和谐的生活环境。 1. 促进社区互动与归属感城市空间设计首先关注的是人与人之间的联系。…

「土地那些事儿」我国土地资源的特点:多样而丰富

土地,作为自然资源的核心,承载着国家的经济发展、社会进步和生态安全。我国作为世界上人口最多、面积第三大的国家,土地资源的特点尤为显著。站在这片古老而又充满活力的土地上,我们不禁会思考:我国的土地资源有哪些独特之处?今天,就让我们一起走进这片广袤的土地,探寻…

三维立体自然资源“一张图”

随着信息技术的发展,自然资源管理迎来了新的机遇与挑战。在众多技术中,“三维立体自然资源‘一张图’”的概念尤为引人注目。它不仅代表了地理信息科学领域的最新成果,也为自然资源的有效管理和可持续利用提供了强有力的支持。本文将探讨这一概念的内涵及其在自然资源管理中…

从Anaconda到PyTorch到训练Yolo——Windows系统

1、Anaconda conda能管理不同的开发编译环境,互补干涉影响。 Anaconda和Miniconda是conda的工具,前者带界面(大而全),后者只有命令行窗口(小而精)。作为初学,建议安装Anaconda 1.1 安装Anaconda 下载 Download Anaconda Distribution | Anaconda ,安装到D盘,其他默认…

9月28日,工信部人才交流中心CUUG-PGCA/PGCP/PGCM认证考试完成!

2024年9月28日,由工业和信息化部人才交流中心主办,北京神脑资讯技术有限公司承办的PostgreSQL管理员岗位能力认证考试(PGCP中级/PGCM高级)顺利完成。 中级PG认证专家:PGCP(PostgreSQL Certified Professional),是对PostgreSQL数据库技术能力的一种认可,达到了专家级别…

设置GRUB密码

通过在GRUB配置中设置密码,系统在启动时会在显示GRUB菜单之前提示用户输入密码,只有输入正确的密码后,用户才能看到并修改启动选项。 1、以 root 用户身份执行 grub2-setpassword 命令。2、检查 /boot/grub2/user.cfg 文件,其包含哈希格式的密码。3、配置GRUB菜单作者:杨灏…

模糊查询用逗号分隔开的字段

业务:一个sys_dept部门表中,有一个字段ancestors是用逗号分隔开的id。 想模糊查询这个字段。 如果用普通的like的话。 select * from sys_dept where ancestors like %1%实现不了我们想要的效果。 mysql 可以用FIND_IN_SET()这个函数来协助。 列:SELECT * FROM sys_dept …

Prism IOC的依赖注入

IOC的依赖注入一、构造函数方式的依赖注入默认情况下Prism框架的项目,在打开窗口时会自动匹配主窗口的视图模型类(PrismApplication启动),这里是MainWindowViewModel,匹配到之后Container自动创建MainWindowViewModel的实例,创建时会先检查MainWindowViewModel有没有无参…

活体标签的内部主芯片-SI24R2F+

Si24R2F+ 是一颗工作在2.4GHz ISM 频段,专为低功耗无线场合设计,集成嵌入式发射基带的无线发射芯片。工作频率范围为 2400MHz-2525MHz,共有126个1MHz带宽的信道。Si24R2F+ 采用GFSK/FSK 数字调制与解调技术。数据传输速率与 PA 输出功率都可以调节,支持 2Mbps,1Mbps,250Kbp…

20242822《Linux内核原理与分析》第二周作业

实验楼上配套实验一 1.创建main.c文件 touch main.c vim main.c2.将main.c文件编译成汇编代码 gcc –S –o main.s main.c -m32 这条命令的含义是:gcc: 调用 GCC 编译器。 -S: 只生成汇编代码,不生成可执行文件。 -o main.s: 指定输出文件名为 main.s。 main.c: 输入的 C 源文…

从0到1搭建权限管理系统系列四 .net8 中Autofac的使用(附源码)

说明该文章是属于OverallAuth2.0系列文章,每周更新一篇该系列文章(从0到1完成系统开发)。该系统文章,我会尽量说的非常详细,做到不管新手、老手都能看懂。说明:OverallAuth2.0 是一个简单、易懂、功能强大的权限+可视化流程管理系统。 友情提醒:本篇文章是属于系列文章,…