codeforces 2100左右的DS题 做题记录
题单地址:https://www.luogu.com.cn/training/1576#problems
动态更新中~~
神 KnightL 说:“这些题还算 DS ?”
反正我不会就对了。/kk
经验之谈
- 找到答案的关键性质。CF1299C
- 或者找到题目的关键性质。CF446B
- 对问题的转化,把它变成一个经典的贪心模型。CF55B
- 神奇的构造方式,按状态建树。CF707D
CF191C Fools and Roads
树上差分随便做。
CF1299C Water Balance
发现答案是单调不降的。
然后维护一个单调栈,栈内的元素包含一段区间的信息,如果上一段区间的平均值大于这一段区间的平均值就将它们合并。
CF446B DZY Loves Modification
你发现行和列之间没有影响。
所以你可以用堆搞出只选行的情况下的前 \(k\) 大,列同理。做一个前缀和存 \(h_i,l_i\) 里。
考虑重合的部分怎么算?假设共选了 \(i\) 行 \(k-i\) 列,那么重合部分为 \(i \times (k-i)\)。
最终答案为 \(\max\{h_i + l_{k-i} - i \times (k-i) \times p\}\)。
CF555B Case of Fugitive
转化一下这个问题,对于所有相邻的两段区间 \([l_{i-1},r_{i-1}],[l_i,r_i]\),你发现它需要的线段的长度在 \([l_i - r_{i-1},r_i - l_{i-1}]\) 内,把线段看做点,然后就转化成了多个区间用点覆盖的模型,贪心即可。
CF707D Persistent Bookcase
你发现 \(1,2,3\) 操作都很好做。(是吗?)
对 \(3\) 操作记录一个 \(rev\) 数组,对 \(1,2\) 操作用 \(vis\) 数组记录。
如何处理 \(4\) 操作?
把操作看作点,然后一个操作向下一个操作连边,dfs 即可。
具体来讲,对于 \(4\) 操作,可以加一条 \((k,i)\) 的边,其他操作可以加一条 \((i-1,i)\) 的边。
CF429D Tricky Function
发现 \(g(i,j)\) 可以写成前缀和的形式:\(g(i,j) = sum_j - sum_i\)
然后整个式子变成了 \(f(i,j) = (i-j)^2 + (sum_j - sum_i)^2\)。
发现这个式子和平面间两点距离公式很像,少了个根号而已。
然后就是一个平面最近点对问题。
这里用一个比较玄学的做法,按纵坐标排序,然后每个点只比较它的后 \(s = 5\) 个点。
CF842D Vitya and Strange Lesson
把异或的值单独储存。
然后把 \(a\) 序列都扔进一个 Trie 里。
然后在 Trie 树上二分 \(\text{mex}\) 即可。
具体细节说不清,去看代码就行。
CF56E Domino Principle
右边的骨牌不会对左边的骨牌造成影响。
如果左边的骨牌能压倒右边的骨牌,那么它一定能压倒右边的骨牌能压倒的骨牌。
从右向左处理即可。
CF912D Fishes
统计某个位置的鱼能被网住多少次。显然需要找到最优的 \(k\) 的位置,然后除以网能网多少位置。
显然中间的最优,剩下的 bfs 找就行。
计算公式比较牛逼。一个 \((x,y)\) 的鱼,能被网到 \((\min(x+r-1,n) - \max(x,r) + 1) \times (\min(y+r-1,m) - \max(y,r) + 1)\) 次。
\(\min(x+r-1,n)\) 求的是网的右边界,\(\max(x,r)\) 求的是网的左边界。
CF817E Choosing The Commander
这个也是个异或最大值,上 Trie 树。
和 CF842D 一样要记录一棵子树内有多少数。
CF702E Analysis of Pathes in Functional Graph
倍增裸题。
一开始想成了树剖 /kx
CF1195E OpenStreetMap
单调队列裸题。类似于 理想的正方形。