「2022-8-15 做题笔记」差分 & 并查集 & 树剖

Minimum Cut
还是很妙的。

考虑一种做法是主席树:对于非树边 \((x,y)\)\(x\in [dfn_i,dfn_i+siz_i-1]\)\(y\notin [dfn_i,dfn_i+siz_i-1]\)。主席树维护即可。

当然,这种问题我们一般看 \(x\)\(y\) 的路径上有没有什么限制,发现一条非树边仅能给 \(x\)\(y\) 的路径上的边提供贡献。

所以树上差分即可。


Fibonacci Additions

差分。广义差分。


Juju and Binary String
个数最少 -> 有可能只是 \(1\)\(2\)

为什么题目一定要求与原串的可爱度相等。鸽巢原理?

然而,转化一下,令 \(A\) 为原串 \(1\) 的个数,\(B\) 为原串 \(2\) 的个数。如果是 \(1\),就加 \(B\),是 \(2\) 就减 \(A\)。即求总和为 \(0\) 的子串。

发现,因为原串总和为 \(0\)。所以子串一定会由正 -> 负,或 负 -> 正。由于每次修改 \(1\) 的个数只会增加 \(1\) 个,所以是连续的,所以一定有一个子串和为 \(0\)。做完了。


「JOISC 2014 Day3」电压
出题人的思路很精妙。

删掉这条边后没有奇环。

分类讨论。若没有奇环,每一条边都可以。

如果它不是树边。那么它一定在唯一的奇环上(与剩下的树边组成)(与其他非树边组合不会产生影响,可以推一推)

如果它是树边。那么它一定在所有的奇环中,且不在偶环中

树上差分即可。注意多个连通块拼起来是有细节的。


「JOISC 2019 Day2」两道料理
。。。dp 的状态就是 \(n^2\) 的啊。。。

能不能基于线段树操作?

转化成笛卡尔坐标系,注意到这里只有两个选法,对应坐标系中的横纵坐标。

每个贡献都可以转化为一个坐标。对于盖饭 \(i\) 的贡献,有个坐标 \((i,p_i)\)。如果我们的路径在它下面(或包含它),那么这个贡献可取。

对于咖喱 \(i\) 的贡献,有个坐标 \((q_i,i)\)。如果我们的路径在它上面(或包含它),那么这个贡献可取。

一个上面一个下面。不好统一。那就简单容斥一下。强制都选咖喱,咖喱的贡献就与盖饭统一了。

\(dp_{i,j}\) 为走到 \((i,j)\) 的最大贡献。\(dp_{i,j}=\max \{dp_{i-1,j}+val_{i-1,j},dp_{i,j-1}\}\)。就是,我们钦定在一个竖条的最高的位置统计答案。

发现对于同一个 \(i\)\(dp_{i,j}\) 是单调递增的,而且 \(val_{i-1,j}\) 发生改变的位置只有 \(2n\) 个,因此想到差分。

如果加的是个正数,差分数组直接加即可。

如果加的是个负数,考虑差分数组中不会出现负数,所以往后一直推,使 \(d_i=d_{i}+d_{i-1}\)\(d_i\) 为非负数时停止。由于每推一下会使差分数组中多出现一个 \(0\),只要我们往后只推有值的地方,均摊次数是 \(2n\)。当然加上最后那个有值的点就是 \(4n\) 啦。

这个东西可以用 \(\mathrm {set}\) 维护,时间复杂度 \(\mathcal {O}(n\log_2n)\)

当然也可以用线段树上二分维护,就不用考虑均摊了。


CF1446D1 Frequency Problem (Easy Version)
CF1446D2 Frequency Problem (Hard Version)
😓

不会。。。考虑答案区间众数与全局众数的关系。

发现:区间众数一定包含着全局众数。(这个可以手玩找规律)

因为假设我们已经得到了一个答案区间。我们可以一直扩展区间,使得区间众数数量等于全局众数数量。

那么,如果区间众数有很多个,答案就是 \(n\)

\(\mathcal {Easy\ Version}\)\(a\leqslant 100\)。考虑固定左端点,右端点肯定选能选到的最远位置,满足众数的个数不超过 \([l,n]\) 全局众数的最大出现次数。等等,主席树上二分可以做到 \(\mathcal {O}(n\log_2n)\)。吊打标程了。(?)(有时间再来检验)

但,枚举每一个数。做一遍前缀和,如果是全局众数就减 \(1\),是这个数就加 \(1\)。答案转化为相距最大的 \(pre\) 相等的位置。桶记录一下即可。

\(\mathcal {Hard\ Version}\)

  • 上面做法最远似乎扩展到值域为 \(\sqrt n\) 的情况。

  • 考虑关注区间众数出现次数。
    如果 \(>\sqrt n\),这样的数只有 \(\sqrt n\) 个。可以使用刚才的算法。
    如果小于 \(\sqrt n\)出现次数 \(< \sqrt n\),枚举出现次数 \(i\)。固定右端点,发现左端点就是最远的使区间里的数出现次数都 \(\leqslant i\) 的。\(\mathrm {two\ pointers}\) 即可,但要判断是否合法,即出现次数最多的数是否有两个及以上。

时间复杂度 \(\mathcal {O}(n\sqrt n)\)

现在看来做法真的很自然。


CF1023F Mobile Phone Network
image

一开始想到的启发式合并。

\((x,y)\) 的并查集根节点为 \(u\)\(v\),对于边 \((s,t)\),如果 \(fa_s=u,fa_t=v\),那么就确定值为 \((x,y)\) 的值。用 vector 维护。但是这个复杂度会伪。。。(不过出题人应该不会刻意卡这个(?))

先对值确定的边跑一遍 mst?

好吧,先固定这些边,剩下的加进来跑 mst。然后没加进来的在树上做个最大值覆盖就可以了。

posted @ 2022-08-16 08:22  Saintex  阅读(43)  评论(0编辑  收藏  举报