DP 选做 #2
DP 选做 #2
Problem A. CF626F Group Projects
贡献和 \(a_i\) 的标号没关系,只和每个集合的 \(\max,\min\) 有关。于是可以先对 \(a\) 排序。
排序后,每个集合可以抽象为一条线段,贡献是这条线段的长度。
于是可以设 \(f_{i,j,k}\) 表示前 \(i\) 个元素,分出 \(j\) 个线段,不和谐度为 \(k\) 的方案数,\(i\) 作为开头贡献 \(-a_i\),作为结尾贡献 \(a_i\)。
但此时复杂度 \(O(n^2\sum a_i)\)。考虑优化,一条线段从 \(i-1\) 延长到 \(i\) 会贡献 \(a_i-a_{i-1}\),于是可以实时维护贡献和,\(O(n^2k)\)。
https://codeforces.com/contest/626/submission/275946899
Problem B. [AGC035D] Add and Remove
想到区间 DP。如果枚举 \([l,r]\) 中第一个删掉 \(p\),两侧的区间会相互影响,不能直接拆分。
正难则反,枚举 \(p\) 是 \([l,r]\) 中最后一个被删掉的,那么 \([l+1,p-1],[p+1,r]\) 就是独立的子问题了。
但还是不好算贡献,因为不知道每个元素到底会贡献多少倍。考虑从外向内来做,\([1,n](p)\) 的 \(a_p\) 一定会贡献 \(2\) 倍,\([p,n](q)\) 的 \(q\) 一定会贡献 \(3\) 倍。所以如果 \(a_l,a_r\) 分别贡献 \(x,y\) 倍,\(a_p\) 就会贡献 \(x+y\) 倍。
于是设出状态 \(f_{l,r,x,y}\),转移 \(f_{l,r,x,y}\leftarrow f_{l,p,x,x+y}+f_{p,r,x+y,y}+a_p(x+y)\)。
每个 \(x,y\) 每次被分为两个,乘上区间个数,总状态数上界为 \(O(n^22^n)\)。
如果加上记忆化,时间复杂度上界就是 \(O(n^32^n)\)。如果不加,上界即为 \(T(n)=\sum (T(n-i)+T(i))\),\(n=18\) 时约为 \(8\times 10^7\),也可以通过。
https://www.luogu.com.cn/record/172142123
Problem C. [AGC039E] Pairing Points
上来肯定先破环为链,设 \(k\) 与 \(2n\) 连边,那么拆出了 \([1,2n-1]( k)\) 这条链。
考虑怎么计算 \([1,2n-1](k)\) 的答案。一定有 \(\ge 1\) 条弦与 \((k,2n)\) 相交,而且这些弦两两不交叉。
枚举最靠近 \(1,2n-1\) 的弦是 \((x,y)\),分为 \([1,k-1](x),[k+1,2n-1](y)\) 两个问题。但除了 \((x,y)\) 还可能有其他连边,还是不好做。
考虑 \(x,y\) 向下一定有一个分界点 \(p,q\),使得 \([x+1,p],[q,y-1]\) 中的点都向 \((x,y)\) 的方向连边,\([p+1,q-1]\) 都向另一侧连边。于是这三个部分之间没有互相连边了。枚举 \(p,q\),分为子问题 \([1,p](x),[p+1,q-1](k),[q,2n-1](y)\),彼此独立。
复杂度 \(O(n^6)\),常数巨小,可以通过。注意边界。
https://atcoder.jp/contests/agc039/submissions/68619980
Problem D. CF1149D Abandoning Roads
考虑求 MST 的过程:先只考虑 \(A\) 边,能连就连,形成若干个连通块,再用 \(B\) 边将连通块串起来。
于是一条路径在某一条 MST 上,当且仅当没有重复经过某一 \(A\) 连通块两次。
考虑状压,设 \(f_{x,s}\) 为 \(1\) 到 \(x\) 已经经过 \(s\) 集合中的连通块的最短路。BFS 做到 \(O(2^nm)\)。
注意到把同一连通块内的 \(B\) 边判掉后,大小 \(\le 3\) 的连通块不可能重复经过。由于 \(2B\) 不一定小于 \(3A\),大小为 \(4\) 的连通块可能重复经过。
所以只需记录大小 \(\ge 4\)连通块,复杂度 \(O(2^{\frac n 4} m)\)。
https://codeforces.com/problemset/submission/1149/334395570
Problem E. P13961 [ICPC 2023 Nanjing R] 华丽收场
大战 2.5h 切掉。
设 \(f_{i,j,k,l}\) 为前 \(i\) 张,手里有 \(j\) 个 \([1]\),\(k\) 个 \([2]\),上限为 \(l\),是否可行。\(O(n^4)\)。
然后可以将 \(l\) 加到状态里,设 \(f_{i,j,k,0/1}\) 为前 \(i\) 张牌,手里有 \(j\) 个 \([1]\),\(k\) 个 \([2]\),目前有没有达到上界,最小上界。\(O(n^3)\)。
观察转移,过程分为两部分,前半部分没有达到上界,后半部分一直卡着上界。前半部分不用弃牌,后半部分和上界具体是多少没有关系,各有一个优美性质,可以分开做。
对于前半部分,若当前手牌数量为 \(j\),则一定使用了 \(j-n\) 张 \([2]\),\([0],[1]\) 的当前数量也不难求出。所以设 \(f_{i,j}\) 表示前 \(i\) 张牌剩 \(j\) 张是否可行,\(O(n^2)\)。
对于后半部分,设 \(g_{i,j,k}\) 为手里有 \(j\) 个 \([1]\),\(k\) 个 \([2]\) 能否把 \([i,n]\) 抽完。然后把 \(k\) 放进状态里,也可以 \(O(n^2)\) 求。
枚举分界点和前面的手牌数,利用 \(g\) 判断是否可行即可。

浙公网安备 33010602011771号