2024.9 做题笔记
CF1575I Illusions of the Desert
看这个边权这么复杂,猜测其必然有一些性质。对 \(a_u,a_v\) 的正负分讨易得 \(\max(|a_u+a_v|,|a_u-a_v|)=|a_u|+|a_v|\),树剖树状数组单点修改链求和即可。
ABC177F I hate Shortest Path Problem
考虑 dp,设 \(f_{i,j}\) 表示到达第 \(i\) 行第 \(j\) 列的最短路。
因为到了某一行后再向右走一定不会更优,所以每次更新后的最短路一定是向下走得到的,所以规定 \(f_{i,j}\) 必须向下走,同时对于右没用的点我们先不管他。
那么:
\(f_{i,r+1}=\min_{l \le i \le r} f_j-j+r+2\)
\(f_{i,j}=f_{i-1,j}+1,j \notin [l,r]\)
\(f_{i,j}=+\infty ,j \in [l,r]\)
线段树维护 \(f_{i}\) 即可,变成正无穷可以加上一个大数。
P8446 虹色的北斗七星
确定了 \(\max-\min\),那么区间显然不会再扩大了,所以 \(\max\) 和 \(\min\) 应该是区间的两端。
那这就是简单题了,求
即可。为啥这样保证了 \(\max \ge \min\) 呢?其实是不保证的,但是 \(\max-\min<0\) 显然不优啊。
CF1227D2 Optimal Subsequences (Hard Version)
和最大,所以是前 \(k\) 大的数。字典序最小,则相同的数先放前面的。
按值域从大到小插入数,然后每个询问第 \(k\) 个数。那么就是当前插入位置下标的第 \(k\) 小,树状数组上二分解决。
确定了插入顺序,可以用离线技巧来解决问题。
CF1227F2 Wrong Answer on test 233 (Hard Version)
首先写个 dp:\(f_{i,j}\) 表示前 \(i\) 道题多对了 \(j\) 道的结果,注意 \(j \in[-i,i]\)。
感觉上这个东西具有对称性,事实上也确实如此。所以只需要用总方案数 \(k^n\) 减去没有相对变化的方案数再除二即可。
没有变化的怎么求呢?考虑两个相邻数如果相同不会有任何影响,记不同的相邻数的个数为 \(m\)。枚举答对的个数 \(i\),那么没答对的也是 \(i\)。
所以 \(f_0=k^{n-m}\sum_{i=1}^{\lfloor \frac{m}{2} \rfloor}\binom{m}{i}\binom{m-i}{i}k^{m-2i}\),计算即可。
CF551E GukiZ and GukiZiana
询问相当于找左侧和右侧的第一个 \(y\)。像找一个数这种操作,我们可以把它转化为二分找第一个大于等于的,然后看是不是这个数。
分块,类似区间 \(\le x\) 的数的个数那样维护即可。
CF1117G Recursive Queries
考虑 \(f(l,r)\) 实际代表的的是笛卡尔树上 \([l,r]\) 的点的子树中在 \([l,r]\) 间的大小之和。
我们知道,如果没有区间的限制,笛卡尔树上的点的子树中的点编号连续,这一点可以根据 \([l,r]\) 的区间最值是 \(l\) 和 \(r\) 的 LCA 轻松推出。记 \(L_i=\max_{j<i,a_j>a_i}j,R_i=\min_{j>i,a_j>a_i}j\)。那么 \(x\) 的子树中的点其实就是 \([L_x+1,R_x-1]\)。现在有了 \([l,r]\) 这个限制,但编号仍是连续的,所以此时 \(x\) 的贡献就是 \(\min(r,R_{x}-1)-\max(l,L_x+1)+1\),从实际意义上考虑,这个式子一定不会有负数。
所以总的答案为 \(\sum_{i=l}^r \min(r,R_i-1)-\max(l,L_i+1)+1\)。
考虑求 \(\sum_{i=l}^r \min(r,R_i-1)\)。只需查询 \([l,r]\) 中有多少数 \(> r\) 并维护 \(\le r\) 的数的和,这样的话需要使用主席树。拆成 \(l-1\) 和 \(r\) 两个询问。需要使用四个树状数组做扫描线即可。
这也太麻烦了,能不能先进一点?考虑用树状数组维护当前的贡献序列而非值域,倒序枚举 \(r\),那么每次只会有 \(R_i-1=r+1\) 的贡献由 \(R_i-1\) 变为 \(r\),更新即可,这样只需要一个树状数组。
P1435 [IOI2000] 回文字串
你先别急。
考虑对于原序列中已经回文的部分,我们不需要去动它。对于不回文的部分,我们需要给每个位置对应放上一个字符。所以答案是 \(|S|\) 减去 \(S\) 中最长回文子序列的长度。
这个回文子序列怎么求呢?可以区间 dp。有一种很巧妙的做法是:因为是回文的,所以倒过来也该出现,所以就是 \(S\) 和 \(\operatorname{rev}(S)\) 的 LCS。
P5662 [CSP-J2019] 纪念品
因为购买无限制,所以可以把一段长的持有拆成若干个相邻天的持有。然后做 \((T-1)\) 遍完全背包即可。
这里的完全背包其实描述的是第 \(i\) 天买入,第 \((i+1)\) 天卖出得到的收益,所以不要做最后一轮,同时这也保证了最后全部卖出。
这道题的思想主要是把一个复杂而不好描述的东西通过给定的条件拆分成简单而容易维护的东西,进而得出做法。
P5268 [SNOI2017] 一个简单的询问
\(f(n,x)\) 表示 \(1 \sim n\) 中 \(x\) 的出现次数。
\(ans=\sum_x (f(r_1,x)-f(l_1-1,x))(f(r_2,x)-f(l_2-1,x))\)
\(=\sum_x f(r_1,x)f(r_2,x)-f(r_1,x)f(l_2-1,x)-f(l_1-1,x)f(r_2,x)+f(l_1-1,x)f(r_1-1,x)\)。
考虑一个 \(\sum_x f(n,x)f(m,x)\) 的求法。
使用莫队,若添加了一个 \(x\),此时在改 \(m\),\(f(m,x)\) 要加一,那么增量是 \(f(n,x)\)。
通常区间的莫队的扩展方式和这题不太一样,为了正确更新要仔细分析一下 \(l,r\) 的初值。
通过差分减少一个询问的限制条件使其易于求解。同时,莫队让我们只需要计算一个点对一段定数的贡献,极大地简化了问题。只需要进行简单的贡献增删就能保证求解的答案正确。
CF1805D A Wide, Wide Graph
考虑一个固定的 \(k\) 和一个点 \(u\):
若距点 \(u\) 最远的点距离 \(<k\),那么它将是孤立点。这个距点 \(u\) 最远的点一定是直径的一个端点。
否则,\(u\) 和直径的某个端点距离 \(\ge k\),那么直径长度 \(\ge k\),所以直径的两个端点和这些点都是联通的。
因此答案为孤立点个数,若直径长度 \(\ge k\) 答案还要再加一。
[ABC267F] Exactly K Steps
还是求出直径 \(u \to v\),找到距离每个点最远的点。同时,以 \(v\) 为根对整棵树进行 dfs。
若一个点到其他点的最远距离 \(<k\),那么无解。若一个点的深度 \(\ge k\),那么直接求出它的 \(k\) 级祖先即可。
否则,距它最远的点一定是 \(u\),假设 \(u\) 与当前点的距离为 \(L\),那么求出 \(u\) 的 \(L-k\) 级祖先即可。

浙公网安备 33010602011771号