08.05
CF1672E
有显然的 \(n \log n\) 次做法,对每种行数二分最短列数,但这样求出的信息太多了。
那么一个初步的想法是想办法淘汰掉不优的选择。
少二分几次,二分什么的信息量最大呢?把总长度二分出来即全部放在同一行,对于放 \(h\) 行,它能更新答案当且仅当 \(w_h \cdot h < S + n -1\),其中 \(S\) 为总长度。这个限制很严,不能让 \(h\) 更大因为此时每个单次后面都会有一个空格,但又最少会放 \((S+n-h)/h\) 行,因此唯一一种方法是 \((S+n-1)/h\),问 \(O(n)\) 次即可。
询问次数 \(\log n + n\)。
CF1354G
先找一块石头。因为 \(k \leq n/2\),随机 \(25\) 次,将当前最大的物品和它比较,留下的东西不是石头的概率是 \((1/2)^{25}\)。
接着倍增跳前缀以找到第一个有礼物的区间。找到后在里面二分。总复杂度是 \(2 \log n - \log_2(C)\),其中 \(C\) 是错误率。
HDU7393
把人分成 \(n/m\) 组,每组 \(m\) 人,想办法让每组有一个人猜对就行了。想办法让一组人猜一整个剩余系。设其他人的和为 \(S\),第 \(i\) 个人猜 \(S+i\) 即可。\(S + a_i\) 的和为定值,每个人猜这个数 \(\bmod m\) 的值,一定恰一人是对的。
agc004F
图是树或基环树。
相邻点处理容易想到二分图,树就是二分图。
黑白染色,则同时变色等价于交换异色点位置。这顺带说明了黑白点个数必须相同。对于一条树边,若其子树内黑白点的差距为 \(t\),则这条边必须至少被经过 \(|t|\),答案下限为 \(\sum |t|\)。
接着是基环树。如果环是偶环,随便断一条边。设断边的流量为 \(x\),则断边左边的值全部都应该加上 \(x\),断边右边的值全部都应该减去 \(x\),这里的左右事实上相对根而言,即右边指的是断边在环上点与根(也是环上点)的路径,左侧则是环上除去路径的那一段。距离变成 \(\sum |a_i-x| + \sum |b+i+x| + |x|\),直接取中位数即可。
好像挺自然的啊。
CF1450C2
经典题。
把图三染色,一定有一种方法的目标次数不超过 \(k/3\)。
TopCoder13366
不存在四元环。如果存在的话根据连边方式可以证矛盾。
环的期望数量是每两个点形成环的概率的和。算一下就行了。
AtCoder-codefestival_2016_final_g
Krustal 的过程中,边被排序,从小到大试图勾通两个连通块。
当考虑到 \((A, B+1, C+1)\) 时 \((A, B, C)\) 一定被考虑过,转而考虑 \((B, B+1, C+1)\) 是不劣的。
因此现在有两种边,一种边只有 \(O(m)\) 条,另一种边只出现在相邻两个点间,边权递增。
Krustal 时,若考虑到 \((A, A+1, C)\) 时已连通,可以放弃所有 \((A+i, A+i+1, C+i)\),因为使 \((A, A+1, C)\) 连通的方案整体右移就可以得到不劣的 \(A+i \to A+i+1\) 的方案。
另一个方法是跑两圈 dp 更新相邻两条边的最小值。复杂度瓶颈并不在此。
HDU6664
题面都没看懂。 看懂了
一个房间经过多次只算一次,不可以状压全部房间,但是可以随机 \(k\) 染色并钦定产生贡献的房间的颜色不同。随机很多次取 \(\max\) 即可。
agc006d
好怀念那个时候啊。
先二分答案。二分答案完后变成 \(0/1\)。如果有两个 \(11\) 或 \(00\) 相邻则它们会一直相邻。于是找到离中心最近的两个相同的数值即为答案。
QOJ141
A 传编号 \(\bmod 4\) 就行了,B 自己把它再双染色一下。
度数小于 \(8\) 的点不需要传,这就够了。
CF1372F
假设知道 \(a_i=v\) 且 \(v\) 出现 \(k\) 次,问左右两个大小为 \(k\) 的区间即可确定位置。
分治,每次处理 \([l, r]\) 中所有数。对于该区间内区间众数 \(x\) 及其出现次数 \(y\),若知道 \(a_p=x\) 则可直接求出 \(x\) 的所有出现位置。否则从区间最大的未确定值的数字开始往右跳,每次跳 \(y\),直到找到 \(x\) 为止。
我挺好奇这个做法的正确性的。好像与 CF 官方题解的两个做法都不大一样。
现在完全懂了,和第一个做法本质一样的。
一份机翻的官方题解:
解决方案 1
我们将定义一个递归函数 \(determine(l,r)\),使用查询来确定数组。我们还将存储一个以前返回的查询值 \((x, f)\) 的辅助列表--不是查询本身,而只是返回的值,这样我们就知道,如果列表中出现 \((x,f)\),那么以前的某个查询显示在某个查询中有 \(x\) 的 \(f\) 实例,而我们还没有确定这些 \(x\) 的 \(f\) 实例在数组中的确切位置。
执行 \(determine(l, r)\) 的过程如下:首先,查询区间 \([l,r]\),结果为 \((x_1,f_1)\)。
如果我们的辅助列表中存在某个先前的查询结果 \((x_1,f_2)\),那么我们将通过 \(determine(l, r)\) 中有待解释的细节来保证,产生该结果的区间包含 \([l,r]\),并且 \(x_1\) 的 \(f_2\) 出现次数中没有一部分出现在 \([l, r]\) 的左边。这样,我们就可以准确地确定 \(x_1\) 的 \(f_2\) 出现的位置。我们在答案中标记这些出现点,然后从辅助列表中删除 \((x_1,f_2)\),不再添加 \((x_1,f_1)\)。如果 \([l, r]\) 并不完全由 \(x_1\) 的出现次数组成,那么对于某个 \(r'\),区间的余数必须是 \([l,r']\),在这种情况下,我们就调用 \(determine(l,r')\)。
如果我们的辅助列表中不存在之前的查询结果 \((x_1,f_2)\),那么我们就将 \((x_1, f_1)\) 添加到列表中,并执行以下操作:当 \(x_1\) 出现的 \(f_1\) 的确切位置尚未确定时,调用 \(determine(l',l'+f_1-1)\),其中 \(l'\) 是 \([l, r]\) 中尚未确定的最左索引。确定这些位置后,调用 \(determine(l',r)\)。
要确定整个数组,我们只需调用 \(determine(1,n)\)。很明显,这将正确地确定数组。我们可以看到,它最多使用 \(4k\) 次查询,具体如下:对于我们添加到辅助列表中的查询结果 \((x, f)\) 所代表的每个同值整数块,我们使用 \(2\) 次查询来确定这些整数的确切位置:在列表中添加 \((x, f)\) 时使用一次,在列表中删除 \((x, f)\) 时使用一次。
这并不能保证算法使用 \(2k\) 次查询,因为某些 \(determine\) 调用会将相同值的整数块分割成两个块。不过,我们可以证明,将一个整数块拆分成两个整数块所形成的任何整数块都不能再拆分,因为它们要么出现在查询区间的开始,要么出现在查询区间的结束(完整证明留给读者练习),因此数组中每个不同的值最多产生 \(2\) 个整数块,每个整数块将在 \(2\) 次查询中确定,这意味着该算法最多使用 \(4k\) 次查询。
通过DeepL.com(免费版)翻译
CF1887E
矩形不好处理,但点并不多。把 \((x, y)\) 的颜色为 \(c\) 处理成 \(x \to y+n\) 有一条 \(c\) 的边,抓一个初始边构成的环,每次从正中间劈开,一定至少一个子环没有重复颜色。这样做下去就行了。\(10 > \log_2 n\),所以一定存在方案。
agc044D
编辑距离可以做什么呢?对于一个全 A
的串,编辑距离可以求出来密码中有几个 A
(只使用替换删除);对于 \(T\) 和 \(S\),二者为子序列当且仅当编辑距离 \(=|S|-|T|\)(只插入)。
于是求 \(f(S)\) 表示只保留 \(S\) 中的字符密码是什么样子的,合并 \(f(A)\) 和 \(f(B)\) 需要 \(|A|+|B|-1\) 次操作,哈夫曼树优化合并(不优化好像也行)就行了。
至于这个合并,跑一个归并排序,枚举下一位来自哪个串就行了。也可以把一个串的每一位往另一个串里面插。
CF1696G
分成 \(n\) 组,首先在每组中求最大值,把所有最大值拿出来,再求一次得到的就是全局最大值。
我们考虑从大到小一个个求值。如果当前最大值来自于第 \(i\) 组,将它去掉。如果一个组内数值少于 \(n\) 个,就从其它组非最大值中借数字来用。如果最大值不出自这一组,就把最大值移到该组。
这样的次数是 \(2(n^2 -n + 1)-1\),需要再省掉 \(n\) 次。那么考虑还剩下 \(2n-1\) 个数的局面,这个时候最小的 \(n-1\) 个数值是知道的,每次只用一次操作就可以求出当前最大值了。于是刚好能过。
本文来自博客园,作者:purplevine,转载请注明原文链接:https://www.cnblogs.com/purplevine/p/18343067