DP们
CF1763D Valid Bitonic Permutations
巨大多分类讨论。枚举 \(n\) 的位置 \(k\),分以下几类(默认 \(i<j\),即 \(x\) 位置在 \(y\) 前面)。
-
\(k<i,x>y\)
-
\(k=i,x=n\)
-
\(k>j,x<y\)
-
\(k=j,y=n\)
-
\(i<k<j\)
前 4 种情况均可组合数乱搞,最后一种不会了,我来 \(dp[i][j]\) 表示填了 \(1,2\dots,i\), \(k\) 左边填了 \(j\) 个。枚举到 \(x\) 和 \(y\) 时特判只能放左 / 右而且第二维有限制。直接做。
CF1762F Good Pairs
咕。
CF1774E Two Chess Pieces
一个棋子 \(x\) 必经一个点需要满足下面两个条件或之中的一个:
-
这个点的子树里有 \(x\) 的必经点。
-
这个点的子树中另一个点的最深必经点和这个点深度差大于 \(k\)。
容易理解。
每个棋子的非 1 必经点会贡献两步(从父亲走过去再走回来),算就行了。哪来的dp
CF1808C Unlucky Numbers
把 \([l,r]\) 拆成一堆 \([x,x+10^k)\)(\(x\) 的后 \(k-1\) 位都是 0),每个区间有一个公共前缀,后面随便填。随便填的部分必然全填前面前缀中最小值和最大值之间的数,即没有影响。
共 \(O(\log_{10} r)\) 个区间,暴力跑就行。哪来的dp
当然,可以数位 dp,但是写完了我才发现我不会构造方案/ng。
CF1808E2 Minibuses on Venus (medium version)
赛后补了个循环卷积多项式的,补一下 \(O(\log n)\) 做法。
好的看不懂,咕了。
CF1814E Chain Chips
一个区间一起满足的最小代价是边权和 \(\times 2\)。
转化为选一条边可以满足两个端点,每个端点都要被满足。
再转化一下就是不能有相邻的两条边都不被选。
可以无脑 ddp,但是不优美!
直接线段树维护 \(a[0/1][0/1]\) 表示这个区间左右端点是否满足,合并简单,支持修改。ez
CF1843F2 Omsk Metro (hard version)
考虑序列上怎么做。
考虑固定左端点怎么做。
由于边权是 \(\{-1,1\}\),右移右端点时子段和变化连续,只要 \(k\) 位于最大值和最小值之间就行了。
不固定左端点类似,只要一次位移一个端点一位,变化就是连续的。
因此 \(k\) 在最大子段和 和 最小子段和之间即可。
扔到树上同样,树剖也行,倍增也行。
CF1840F Railguns
观察到答案不会超过 \(n+m+r\),记 \(dp[i][j][k]\) 为能否在时刻 \(k\) 时位置在 \((i,j)\)。但是状态数太多了。又观察到走到 \((i,j)\) 最少要花 \((i+j)\) 步,改写 \(k\) 的意义为 在时刻 \(k+i+j\) 时到达 \((i,j)\),这样状态数就对了。直接做。
CF1827C Palindrome Partition
记 \(dp[i]\) 为以 \(i\) 结尾的合法串数量,为保证不重,我们找到以 \(i\) 结尾的最短偶回文串长度 \(len_i\),那么有若 \(len_i> 0\) \(dp[i]=dp[i-len_i]+1\)。答案即为 \(\sum dp[i]\)。正确性画图可证。
考虑求出 \(len_i\)。
先做一遍马拉车,得出每个 \((i,i+1)\) 为中心的最长偶回文串长度 \(l_i\times 2\),那么 \(len_j=\min_{i+1\le j\le i+len}(j-i)\),拆开来就是 \(len_j=j-\max_{i+1\le j\le i+len}i\)。
从大往小枚举 \(i\),那么一个位置遇到第一个满足条件的 \(i\) 就是最大的 \(i\)。把还没确定 \(len\) 的位置扔进一个 set
里,每次二分出最小位置然后往后把符合条件的位置全做掉,保证每个位置只被遍历到一次。然后就得到了 \(O(n\log n)\) 的求 \(len\) 的做法。
不优美。被电电的单调栈吊打了。
当然优化到 \(O(n)\) 也行,但是要动态维护已确定区间集来找到还没确定的区间。不过我认为并无必要。好写(好想)即正义
CF1826E Walk the Runway
bitset
练习题。
大概就是求出每行内的偏序关系,然后行之间并起来得到城市之间的偏序关系,用 bitset
优化做到 \(O(\dfrac{n^2m}{\omega})\),然后直接暴力建图(显然是个 DAG)跑 dp。
CF1824C LuoTianyi and XOR-Tree
先来点暴力 dp 。
设 \(dp[u][i]\) 为以 \(u\) 为根的子树内把所有到叶子路径的异或和都变成 \(i\) 的最小操作次数。
显然 \(dp[u][*]\) 只有两种取值,因为可以对 \(u\) 进行一次操作将异或和都改变。两种取值相差 1,且能取到较小值的 \(i\) 不超过子树内叶子数。
考虑记录较小 dp 值与取到这个值的 \(i\) 的集合 \(S_u\)(用 map
维护)。子树合并上来就是找 \(S_v\) 中出现次数最多的数。
使用启发式合并,保留 size 最大的 map
,计算其他 map
中出现次数最多的数。由于最大的 map
中的元素只会对出现次数造成 \(\le 1\) 的影响,求出出现次数最多喝次多的数,枚举并判断是否可行。
然后自底向上合并就行了。