闲话 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 的高科技,在时间效率和代码好写程度上都薄纱其它方法的狠活。
思路
建议画个简单图手模一下
设我们要求
首先考虑
再考虑二者存在祖先关系怎么处理。暴力判断虽然可行,但与我们这样做的目的就相悖了,我们要找到一个优雅的方式来求解。由
唯一的不足就是无法处理
实现
借助 ST 表来完成,预处理的复杂度是
模板题代码:
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 赋了一个
差分约束系统 是一种特殊的
嗯,这有啥好说的,还是挑重点吧。
给你若干个形如
思路
联想大法好:发现
如果符号是
实现
公元 4202 年,智慧的人类掌握了复活已死的事物这一技术,并以 SPFA 为对象进行了秘密测试,结果未知。
采用 SPFA 算法,若跑出负环了显然是无解的情况,否则跑出的
由于限制是以差分形式存在的,所以若
例题:无
啊不对,昨天晚上刚做了一道。
例题:有
谔谔虽然你们暴力都过了并且我的暴力改完也过了,但我赛时打的差分约束所以它就是模板题。
很好的条件,确保了一定有解,所以我们完全可以省掉判负环的步骤,直接开局建一个超级原点,按差分的性质连边,跑一遍就没了,因为
Submitted code 这里放的现打的因为赛时太唐了做了一堆唐氏操作,喜欢唐人的可以自己去搜。
lower_bound 妙用
在 vp abc371 的时候想要查一个有序数组中第一个小于等于
食用方法
首先,一般的 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>());
返回值的类型仍然是下标,然后就可以肆意操作了。
准备一个 例题,别的暴力方法可能能过,不过都学了这个了就考虑怎么用线段树做。
首先位置是严格递增给出的,所以不用去管
鲜花
-
1 能不能不要再逆天发言了,哦好像这几个字排列已经被你们发掘完了,怪不得没动静了
-
2
Ratio:jijidawang 你想说点什么吗
jijidawang:我想说点什么吗 -
3
(jijidawang 在翻看上一届的模拟赛成绩)
Ratio:看看最后一名是谁(yzh)
顶针:yanzihe
Ratio:哪个 yan
顶针:yxc 的闫
Ratio:为啥不是我这个颜
顶针:你这个颜太少见了,上次见还是颜丑(认真
5k:颜丑是啥(疑惑
顶针:就三国那个文良颜丑
5k:那不是颜良文丑吗
顶针:哦,反正他俩老在一块
5k:那 huge 和消费股还老在一块呢,你咋不喊朱晓飞
顶针:你咋不倒着念小肥猪
(Upd:知道顶针从哪看的了)
- 4
(吃完饭,CTH 看到对面桌子上放了运动会要用的亚克力举牌,于是过去看了看)
同学:你看吧,弄坏了 50
HDK:有这 50 我都能买一个银狼立牌了
CTH:有 50 我能买亚克力板子给你做个棺材了,到时候让他烧碎一点
……
HDK:谷子店太赚钱了,1 块钱成本卖 10 块都算便宜的
CTH(听成骨灰店,我们也是):人家一辈子就赚你一回钱,多赚点怎么了
HDK:我跟你说它要是卖的好我能成那的老主顾(激动
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】