Duel 记录
· CF204C Little Elephant and Furik and Rubik
容易求出总的匹配对数,即 \(\sum\limits_{i=1}^ni^2\),要求期望只要求 \(\sum f(x,y)\).
考虑每对匹配的字符对 \(\sum f(x,y)\) 的贡献.
因为一对匹配的字符在字符串中的相对位置不变,所以它的贡献就是能同时延伸到的字符串个数.
不妨设第一个字符的位置为 \(i\),第二个字符的位置为 \(j>i\),那么贡献就是 \(i\times(n-j+1)\).
由于字符集大小 \(\Sigma\) 很小,可以枚举 \(\Sigma\) 的字符和第一个字符的位置,动态维护第二个字符的位置的前缀和与后缀和.
- CF2B The least round way
最小化后缀 \(0\) 个数也就是最小化路径上数的 \(2\) 和 \(5\) 的次数.
考虑分别记录 \(2\) 和 \(5\) 的最小次数,较小值即为后缀 \(0\) 的最小个数.
需要特判 \(0\) 存在的情况.
- CF1254B1 Send Boxes to Alice (Easy Version)
只要考虑非零的 \(a_i\) 为同一质因数的情况.
最小距离就是每段与中位数的距离.
+ CF251C Number Transformation
注意到 \(\mathop{\operatorname{lcm}}\limits_{i=2}^{15} \ i = 360360\) 很小,这意味着可以将数轴划分为长度为 \(\operatorname{lcm}\) 的段,不同段相同位置的行为是相同的.
并且可以发现在同一个段中操作最终总是到 \(\operatorname{lcm}\) 的倍数.
于是可以在段内 dp 跳过前面的段,最后一段 bfs 即可.
· CF1930C Lexicographically Largest
每个 \(a_i\) 能贡献的最大数就是 \(a_i+i\). 考虑证明如果两个数贡献的数相同,一定有一个能减 \(1\) 而其它数不受影响.
对于每一个位置 \(i\),其要减的数可以不超过 \(i\),那么必然可以以一定的顺序通过先操作前面的数得到要减的个数.
+ CF1036C Classy Numbers
令 \(f(x,d)\) 表示 \(0\sim x\) 中含义不超过 \(d\) 个非零数字的数的个数.
设 \(B=\lfloor\lg x\rfloor\),那么 \(f(x,d)=f(10^B-1,d)+(\lfloor\frac{x}{10^B}\rfloor-1) f(10^B-1,d-1)+f(x\bmod 10^B,d-1)\).
其中 \(f(10^B-1,d)=\sum\limits_{i=0}^d\binom{B}{i}9^i\).
\(f(r,3)-f(l-1,3)\) 即为所求.
· CF360B Levko and Array
二分答案 \(x\).
令 \(dp_i\) 表示 \(a_i\) 不改变,前面的数使得答案成立最少需要改变多少次.
转移考虑距离 \(i\) 最近的不改变的位置 \(j\).
那么 \(i\sim j\) 间的所有数都可以改变,使答案成立当且仅当 \(|a_i-a_j|\leq (i-j)x\).
+ CF1887B Time Travel
枚举时刻 \(i\),我们只要知道有多少点可以在时刻 \(i\) 第一次被访问到并把它加到访问到的点的集合里.
因为一条边只会贡献一个点,所以可以尝试枚举边加点.
如果边中两点都没被访问到,那么就会被重复考虑,所以每当新点被访问,我们再加入点对应的边即可.
这样所有边都只会被考虑到一次,使用 std::unordered_map
复杂度是 \(O(k+\sum m_i)\) 的.
· CF1995C Squaring
直接从前往后贪心模拟就好了.
因为如果 \(x<y\),那么 \(x^2<y^2\),所以只要记录平方的次数,再在相邻原项模拟.
· CF474C Captain Marmot
判断 \(4\) 个点是否构成正方形. 计算 \(d=\sum\limits_{(\mathbf x, \mathbf y)} (\mathbf x-\mathbf y)^2\),然后判断有没有 \(6\) 对点的距离平方是 \(\frac{d}{8}\) 或者 \(\frac{d}{4}\).
· CF578C Weakness and Poorness
每个区间 $[l,r] $的 poorness 为 \(P(x)=\lvert\sum\limits_{i=l}^r a_i - (r-l+1)x\rvert\) 两段直线,先减后增.
于是 weakness 为 \(W(x)=\max P(x)\) 就是凸的,用三分检验最大子段和即可.
几何做法再说.
+ CF1918D Blocking Elements
二分答案 \(x\).
然后考虑 dp,令 \(f_i\) 表示前 \(i\) 个数 在满足区间和最值约束下 分隔点和的最值.
转移就是部分和小于等于 \(x\) 的最小 \(f\),可以用 map 维护.
+ CF1969D Shop Game
因为 Bob 总是会选 \(b_i\) 最大的 \(k\) 个,钦定 Bob 选择的最小 \(b_i\).
对于 Bob 选择的 \(k\) 个数,选择 \(\geq b_i\) 的 \(a_i\) 最小的 \(k\) 个,可以大根堆动态维护.
对于其他 \(<b_i\) 的数,使用前缀和计算最大收益就可以了.
· CF1184E1 Daleks' Invasion (easy)
删除第一条边求 MST,当第一条边的两个端点合并至同一联通块时计算答案.
+ CF2036G Library of Magic
如果返回的答案不为 \(0\),二分即可找到答案.
不过如果 \(a \oplus b = c\),并且询问的区间同时包含这三个数就会返回 \(0\).
怎么样避免区间同时包含这三个数呢?注意到如果 \(a \oplus b = c\),那么肯定存在一个数 \(1\) 的最高位比其他两个数低.
进一步地,如果 \(a\oplus b = c\),那么 \(2\min(a,b,c) < \max(a,b,c)\).
于是如果询问区间长度等于左端点,必然不会出现包含要找的数且返回 \(0\) 的情况.
我们可以先询问全局异或和,这样就只要找到两个数了.
然后每次询问 \([2^i,2^{i+1})\),如果询问答案 \(x\) 不为 \(0\) 可以二分找到一个数 \(y\),如果 \(x \neq y\) 可以通过消除 \(y\) 的影响再二分找到第二个数.
询问次数是 \(3\log_2 x\),注意到 \(\log_2 10^{18} \approx 60\),最大询问次数 \(150\) 也就是 \(2.5\log_2 N\),直接这样问是会 WA 的.
再怎么减少询问次数呢,考虑从大到小询问 \([2^i,2^{i+1})\). 那样询问的最大次数就变成了 \(\log_2N + \log_2x\),足够通过本题.
还有另一种思考方式,因为 \(a\oplus b \neq c\) 的时候可以二分,所以只要考虑相等的情形,其中两个较大的数 \(1\) 最高位一定相同.
于是可以从高到低查找它们的最高位在哪里. 找到之后,二分就可以了.
然后发现 \(a \oplus b \neq c\) 的时候也可以通过这种做法找到两个较大数的最高位,所以最后的实现和第一种思考方式居然是一模一样的!
+ CF431D Random Task
因为 \(n\) 与 \(2n\) 二进制 \(1\) 的个数相同,所以答案是递增的,且每次最多加一,那么必然有解.
考虑二分,计算 \(f(n,k)\) 即 \(0\sim n\) 的数中恰有 \(k\) 个 \(1\) 的个数.
令 \(B=\lfloor\log_2n\rfloor\),将 \([0,n]\) 拆成 \([0,2^B)\cup [2^B,2^B+(n-2^B)]\),那么 \(f(n,k)=\binom{B}{k}+f(n-2^B,k-1)\).
因为 \(\binom{64}{32}\approx 1.8\times10^{18}\),所以可以直接递推求组合数(当然也可以用 long double
或者用 __int128 在模大质数意义下求组合数).
- CF551B ZgukistringZ
转化为 \(\max\limits_{k=0}^{n}(\min\limits_{i=1}^\Sigma (A_i-kBi)/C_i+k)\).
因为字符集大小 \(\Sigma=26\),直接 \(O(n\Sigma)\) 枚举即可.