9.19 abc371补题 & map 在 dp 上的妙用
昨天的也一起写了。
abc371F:两种做法。等差数列线段树和 ODT。两种做法实现难度相同,不过后者似乎要快很多。
花 1 个小时复习了 ODT 怎么打,他复杂度正确的原因是因为每次 query(l, r) 过后马上进行了 assign。然后就是基础的 split 和 getpos 操作,记得给边界插入 set。
线段树也是维护三元组 【l, r, pos】 表示左右 id。如果有区间操作的话 lzy 就是 pos 表示等差数列的第一项。每次下传标记记得去右儿子的时候把 lzy 加 lenLS,然后一个线段树节点就是由多个等差数列构成。
注意不要写动态开点的线段树,非常容易 TLE。
abc317G:这玩意场上想了一半正解。
考虑到正式考试不可能高精度,所以我们使用正常算法。
这个东西本质上是多个同余方程合并,每次在合法解里面贪心选,显然 lcm 作为模数需要高精度。
注意到如果:\((m_1,m_2)=1\),则必然可以满足。所以我们要对所有 \(m\) 之间的 gcd 来考虑是否满足,eg:\(\mod 2 = 1,\mod 4 = 0\) 显然无解。
又能够想到质数拆分,如果对于所有质数来判断一定是等价的。而质数因数个数显然是亚根号级别。
所以我们顺序遍历每个环,记录环长 \(l\),然后枚举换上第一个应该是本来的第 \(i\) 个,容易发现这样子要转 \(x=l-i\) 次。那么我们就判断可行即可。
对 \(l\) 的所有质因子考虑(这里考虑所有 \(m_i^{a_i}\) 形式),容易发现等价转化后 \(x\mod m_i^{a_i}\) 这个值在所有环上都一样,所以对每个因数记录一个 mod 值即可。
最后贪心选每个环第一个位置最小的即可。复杂度线性根号,远远跑不满。
[SCOI2013] 数数:经典题。
\(num_i\):以 \(i\) 结尾的所有数的个数。
\(len_i\):……的所有数的长度的和。
\(suf_i\) 以 i 结尾的所有后缀的数的和。
\(q_i\):到 i 的总共答案。
考虑放在递推形数位 dp 中,加上 0/1 限制数位即可。代码细节特别多。
[NOIP2021] 方差:场上估计 60~90min 做出来。
这个操作形式不太规整。观察到差分过后一次操作就是交换前后的差分值!所以问题就变成了重新排列差分数组,使得最终的数组方差最小。
方差拆完之后要维护 sumai 和 sum(ai^2)。
然后我们猜测怎么排列差分数组。
注意到差分值单谷 c,这个东西根据我们的暴力跑出来就发现了。
感性理解?肯定是抛物线式的,因为这样才会平均,画一下图就知道单谷显然更好。
知道这个过后呢,排序过后相当于我们是进行一个插在左右两边的区间 dp 了,其实是序列 dp。
wc,dp 状态里面记录 suma,维护 \(\sum ai^2\) 的最大值!这样就做完了。
dp 从最小的点开始,刷表法转移。
发现这玩意过不了最后一个点,因为 suma 是 \(nV\) 级别。所以我转移直接遍历 map 来转移可行状态,发现多一个 log 但是过了。
题解说 \(V << n\),差分值等于 0 的很多,没有贡献,所以相当于 n 变成了 V。其实都是省掉了没用的状态,好像 map 综合表现是更优。
打 map 优化是因为今天 T4 太神了,从那里学来的东西。
Mod Mod Mod
首先典:一次有效模运算 /= 2。
然后使用调整法,得知一定存在一个 \(x\) 卡到 \(a_i\) 的上界位置,否则加 1 显然更优。
于是这就证明了合法的状态数至多只有 \(n\log V\) 个。
像上面一样用 map 记录 dp 数组进行转移,一种是直接 mod ai,一种是直接变成 ai+1 - 1。注意 dp 状态记录的是大于等于 \(j\) 的代价和。
注意循环的时候要这样写:st.erase(it++)
。nb 实现。
又不得不提到一道还是 map 的不规则时间复杂度做法的题。
「agc020E」Encoding Subsets
在这里我们 dp 的状态是字符串。
这里的计数方法是非常典的。不多讲。还是钦定最前面一段不是合并类型的合法,后面随便类型的合法,乘起来即可。
关于不是合并的合法的计算,注意到子集就是循环节里面的字符串取 min,此时本来要区间 dp,但是直接字符串记忆化掉了,nb。
对了,这个题还用到了两个函数的相互调用,nb。