杂项乱写 9.29

news/2024/9/29 11:56:38

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

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


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 这里放的现打的因为赛时太唐了做了一堆唐氏操作,喜欢唐人的可以自己去搜。

鲜花

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

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


完结撒花~

image

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

中电金信:保险企业级数据中台解决方案

​ 01业务痛点数据孤岛 公司中的各个部门都有自己的数据,无法有效 连接或整合,不仅导致信息隔阂,还会影响决 策效率和数据分析的准确性,进而影响整个组 织的运营效率和竞争力。数据复用难题 由于系统的限制,相同的数据在不同的系统中 不能复用,导致需要进行数据重复加工,…

Chrome检查更新时出错:无法启动更新检查(错误代码为 4: 0x80070005 – system level)。

1、快捷键 Win+R 输入:services.msc2、找到 “Google 更新服务 (gupdatem)”,改为手动(如果不行就把gupdate也改为手动) 3、再去更新Chrome就可以了

工作繁杂,如何防止工作遗漏遗忘?

来源:tita.com 不知道大家工作中是否有这样的情况:1.工作过程中工作任务经常被打断,打乱正常的工作节奏; 2.因为不方便统一记录工作及工作要求,经常忘记给领导反馈工作进展; 3.因为工作繁多,经常会出现工作遗漏遗忘的现象。 …… 如果你的工作计划出现了这样的问题,就是…

GaussDB数据库特性-物化视图简介

一、前言 随着企业数据量的不断增长和业务需求的复杂性增加,选择一个高效、可靠且智能的数据存储和管理解决方案变得越来越重要。GaussDB是一种先进的关系型数据库管理系统,为企业提供了强大的数据处理能力,其物化视图(Materialized Views)功能在数据查询和管理方面具有重…

微软账号注册

注册地址 https://signup.live.com/signup 少侠,我看你气度不凡天赋异禀,骨骼精奇,这么帅,来了就帮推荐一把吧 我的最近更新 最新发布文章、框架、咨询等,来看看吧

解决:PC微信弹窗《当前客户端版本过低,请前往应用商店升级到最新版本客户端后再登录》

目录1. 背景 2. 利用cheat Engine直接修改内存 3. 利用Python代码直接修改内存1. 背景虽然人类都是喜新厌旧的,但也不是什么东西都是新的好。今天换了台服务器,发现正常使用微信,弹窗提醒说版本太低了,根本不给登录。没办法啊,机器人只兼容这个版本的,只能到处找解决方案…

黑马PM-内容项目-需求收集管理

什么是需求需求如何收集 常见需求收集方式竞品分析用户访谈实地调研需求管理

浅浅记录学习情况叭

Basic Concepts对于一个给定的网络G=(V,E),其中V为网络的节点集,E为网络的边集. Trace(迹): 将G划分为q个社区,我们用一个qxq的对称矩阵e来表示该划分,e中的每个元素表示连接社区i与社区j的边在G的全部边中所占的比例显然有∑i,jeij=1。矩阵e的迹Tr(e)表示连接社区内部节点的边…