do_while_true

一言(ヒトコト)

若干 trick

CF 570D

一棵树,每个节点上有一个字母,每次查询点 \(x\)\(y\) 级儿子的字母是否能重排成一个回文串。

trick:压位,只有01的信息(在此题中是奇偶性),可以压成一个 int 来并行计算,这样就可以砍掉一个 \(\log\)

用到类似trick的题:由乃的OJ

ARC 127C

给定 \(N,X\),要求在 \([1,2^N-1]\) 的范围内找字典序排名第 \(X\) 小(没有前导零)的二进制数,其中 \(X\) 是以 \(2\) 进制给出的。

首先先假装 \(0\) 存在,这个是不要紧的,令 \(X\gets X-1\)

然后数可以分成三类,\(0\)\(10\) 开头的,\(11\) 开头的,如果 \(X=0\),那么答案就是 \(0\);否则,若 \(1\leq X<2^{N-1}\),那么就是 \(10\) 开头,然后令 \(X\gets X-1\)\(0\) 没有了),若 \(X>2^{N-1}\),说明是 \(11\) 开头,\(X\) 减去 \(2^{N-1}\) 即可。

由于每次减去 \(2^{N-1}\) 的话是砍掉最高位可以 \(\mathcal{O}(1)\),然后 \(-1\) 的话就暴力借位,对于每一位考虑最劣情况下借位次数,其数量是 \(\sum\left \lceil \frac{n}{2^i} \right \rceil =\mathcal{O}(n)\)

trick:对于一个数,每次只有 \(+1\),或者每次只有 \(-1\),暴力进位/借位次数均摊下来是 \(\mathcal{O}(次数)\) 的。

AGC 052B

给定一棵树,每条边有一个初始边权和一个要得到的边权,每次可以选择一条边 \((u,v,w)\),令这条边的所有邻边的权值都异或 \(w\)

考虑边权转点权,让边权满足其为相邻点权的异或和,操作变成交换两个点的点权。

随便钦定一个为根,设 \(d_i\) 为初始时 \(i\) 的点权,\(f_i\)\(i\) 期望得到为多少。如果存在 \(d,f\),满足它们是相同的集合,就有解。

注意到如果确定了一个点的点权,那么其他所有点权都能唯一的确定。

现在钦定 \(f_i\)\(i\) 到根路径上的边权和(或者说钦定 \(f_1=0\)),注意到任何一组解都能把所有点权异或 \(f_1\),得到 \(f_1=0\) 的解,所以判断是否有解就判断 \(f_1=0\) 的时候是否有解。

现在 \(f\) 确定了,看是否存在 \(d\),满足 \(d\)\(f\) 是相同的集合。

现在继续钦定 \(d_i\)\(i\) 到根路径上边权和,与 \(f\) 相同,所有可能为答案的 \(d'\) 都是 \(d\) 异或上一个 \(x\) 得到的。

那么有解的充分条件就是 \((d_1\oplus x)\oplus (d_2\oplus x)\oplus...\oplus (d_n\oplus x)=f_1\oplus f_2\oplus...\oplus f_n\),由于 \(n\) 为奇数,所以可以解出 \(x\) 是多少。

由于这仅是充分条件,那么最后还要 \(\text{check}\) 一下是否合法。

trick:由充分(或者必要)条件可以得出答案可能的一种或多种取值,然后暴力判断必要(或者充分)条件是否满足。

AGC 045B

有个 \(01\) 序列,其中有些位置不确定。要确定这些位置,最小化区间 \(0\)\(1\) 出现次数的差的绝对值的 \(\max\)

作一下前缀和,问题变成使得前缀和的极差尽可能小。先考虑暴力怎么做是不是加边加边并查集,枚举前缀和 \(s\) 的最大值,然后从前往后贪心想使得最小值尽可能大,如果当前能填 \(+1\) 就填 \(+1\),否则填 \(-1\)

观察这个贪心,考虑到枚举的 \(s\) 的最大值 \(+2\) 之后,最多有一个 \(-1\) 变成了 \(+1\),因为上界 \(+2\) 后又 \(-2\),所以从那个位置之后的填法和之前是一样的。所以最大值 \(+2\) 之后,最大的最小值最多会 \(+2\),故不会更优。

所以只枚举可能的最小的前缀和最大值及其 \(+1\) 即可。

trick:先考虑暴力怎么做,然后给暴力剪枝/优化

ARC 128A

初始有 \(1\) 黄金和 \(0\) 白银,接下来 \(n\) 天,在第 \(i\) 天可以选择什么也不做,或者把 \(x\) 黄金换成 \(x\times A_i\) 白银,把 \(x\) 白银换成 \(x/A_i\) 黄金。构造方案使得最终得到黄金最大。

假设现在有 \(x\) 克金子如果在第 \(i\) 天将金子换成银子,紧接着在第 \(j\) 天把银子换成金子,那么 \(x\gets x\times\frac{A_i}{A_j}\)

  • 把限制松一松,一天可以交换多次,发现和原问题等价,交换两次相当于没有交换。
  • 把限制紧一紧,一次对换,即在第 \(i\) 天将金子换成银子,紧接着在第 \(j\) 天把银子换成金子。仅允许 \(i+1=j\) .发现和原问题等价,\(i\) 天金到银,\(j\) 天银到金,等价于 \(i\) 天金到银,\(i+1\) 天银到金,\(i+1\) 天金到银,\(i+2\) 天银到金...\(j\) 天银到金。即 \((i,j)\) 对换,等价于 \((i,i+1),(i+1,i+2),...,(j-1,j)\) 对换。

问题转化成让 \(1\) 克金子,每次可以乘上 \(\frac{A_{i}}{A_{i+1}}\),所以只有 \(A_i>A_{i+1}\) 的时候,才选择对换 \((i,i+1)\)

对应回原问题,一笔交易被对换奇数次才相当于做这一笔交易。

trick:限制松一松/紧一紧发现和原问题等价。

Code

思维不好怎么办?第一眼可以看出暴力 dp,设 \(f_{i,0/1}\) 代表在做完前 \(i\) 笔交易,手里拿的金子/银子的最大克数,转移的时候判断大小,用 \(\log\) 来比较就可以。对应了[Code+#4]组合数问题2这道题的 trick数比较大且运算只有乘除法/次方的时候用 \(\log\) 比较大小。

CF 506D

给定一张无向图,每次询问给定 \(u,v\),求有多少 \(c\) 满足至少存在一条 \(u\)\(v\) 的路径,其颜色均为 \(c\)

想不出来的时候就想暴力,然后优化优化,然后尝试平衡复杂度(虽然这题没有把两个暴力拼起来平衡复杂度)

对于每一个颜色开个并查集,会用到的点数只有 \(2m\) 个。

然后对于一个询问 \((u,v)\),对其中一个点出边的颜色所在的并查集,看 \(u,v\) 是否连通,由于 \(u,v\) 是等价的,所以查询度数 \(d\) 较小的那一边。

如果一个询问询问了多次,可以直接用之前已经得出的答案。

这个复杂度是有理有据的,对于 \(d>\sqrt{2m}\) 的点,最多有 \(\sqrt{2m}\) 个,查询的复杂度为 \(\mathcal{O}(\sqrt{2m}\times \sqrt{2m}\times \sqrt{2m})=\mathcal{O}(m\sqrt m)\)

对于 \(d<\sqrt{m}\) 的点,最多查询 \(q\) 次,查询的复杂度为 \(\mathcal{O}(q\sqrt m)\),如果把并查集的复杂度看成常数的话总复杂度就是 \(\mathcal{O}((m+q)\sqrt m)\)

应该还有其他拼暴力的方法,但这个一个暴力就够了。

CF 383E

给出 \(n\) 个长度为 \(3\) 的由小写字母组成的单词,一个单词是正确的当且仅当其包含至少一个元音字母。这里的元音字母是 a 到 x 的一个子集。对于所有元音字母集合,求这 \(n\) 个单词中正确单词的数量平方的异或和。

设总有效字符数为 \(m=24\)

对于一个集合而言,答案为 包含其中一个字母的单词数 \(-\) 同时包含两个字母的单词数 \(+\) 同时包含三个字母的单词数。

同时包含三个字母的单词数就是完全包含在集合中的单词数,做个高维前缀和就可以了。复杂度 \(\mathcal{O}(2^mm)\)

只看前两项,\(f_S\) 为集合元音字母集合为 \(S\) 时的答案,从 \(f_{S-\mathrm{lowbit}(S)}\) 转移而来。复杂度 \(\mathcal{O}(2^mm)\)

有更简单做法:

经典套路正难则反:与集合有交的集合数 \(=\) 总集合数 \(-\) 与集合不相交集合个数 \(=\) 总集合数 \(-\) 其补集的子集出现次数。

这样一遍高维前缀和就ok了。

CF 715C

给定一棵树,边权 \(1 \leq w\leq 9\)。给定一个数 \(M\),保证 \(\gcd(M,10)=1\)

对于一对有序的不同的顶点 \((u, v)\),他沿着从顶点 \(u\) 到顶点 \(v\) 的最短路径,按经过顺序写下他在路径上遇到的所有数字(从左往右写),如果得到一个可以被 \(M\) 整除的十进制整数,那么就认为 \((u,v)\) 是有趣的点对。

求有趣的对的数量。

树上满足某种条件的路径个数要想到点分治

点分治,对于一个分治中心,求出子树中每个节点自上而下的数字 \(d_1\pmod m\),匹配上另一个自下而上的数字 \(d_2\pmod m\),其深度为 \(k\),要满足 \(d_2+d_1\times 10^k\equiv 0\pmod m\Rightarrow d_2\times 10^{-k}+d_1\equiv 0\pmod m,(\because (m,10)=1)\),开个 map 统计就可以了。时间复杂度 2log(map)或者 1log(unordered_map

CF 555E

给定一张 \(n\) 个点 \(m\) 条边的无向图和 \(q\) 组点对 \((s,t)\),现在要给每条边定向成有向图。

询问是否存在一种定向方案使得所有 \(s\) 都能到达 \(t\)

点对之间是否存在可达路径 \(\to\) Tarjan(不要想支配树了啊喂你又不会建支配树)

按照边双缩个点,缩出来一棵树。一个边双内的点对肯定能互相到达,连出来一个环就可以。现在只有边双之间的点对,看看是否能满足所有的 \(s\to t\),随便钦点一个根,有边既要朝向根又要朝向叶子就不合法,用个树上差分解决。

自己瞎编的边差分竟然是麻烦了,点权代表点和父亲的边权,边差分作子树和更好写。

posted @ 2021-10-23 06:53  do_while_true  阅读(39)  评论(0编辑  收藏  举报