2024.01.25 近期练习

CF1508D

经典套路,把 iai 连边,形成若干的置换环。
注意到我们对于一个环,可以令其变成一个菊花,即不断地对一个点操作消去出边。
如果只有一个环,那么问题轻松解决。
如果有多个环呢,交换其中两个环中的一对就可以变成一个环。
把剩下的点进行极角排序,然后相邻的两个点进行操作:
如果两个点所在的环还没有并在一起就交换这两个点,用并查集维护。
发现这样是不可能与菊花相交,因为这些边都在菊花相邻边之间。
最后再做一遍开头那个算法即可。
这种问题首先应处理排列,关于相交的问题可以用极角排序。

CF1491H

如果没有修改,我们可以借助“弹飞绵阳”的套路,分块,维护跳出这个块到哪。
先考虑查询的话,我们可以像类似树剖那样向上跳,复杂度是 O(n) 的。
修改怎么办?对于散块来讲直接暴力重构。
整块怎么办?由于修改只有 x,如果 x 之和超过块长,那么所有元素一跳就出块了。
所以整块也暴力修改。注意到一个块只会被修改 n 次,复杂度是 O(n)3=n1.5
当一个块超过 n 修改时,直接打个标记即可。
这种大数据结构应考虑分块思想,以及考虑势能分析。

CF1856E2

如果 n5000 考虑怎么做。
首先我们对于每个节点只考虑大小关系,最后只需要从小到大标号即可。
我们考虑把答案放到 LCA 处统计。
若其只有两个儿子 v1,v2,那最多只有 sizv1×sizv2 个会被统计,即令 v1 所有数大于 v2
若有多个儿子,就是把儿子子树的大小分成两个集合,使得两个集合差最小。
可以用 01 背包解决。然而 O(n2)。考虑 n1e6,如何优化 01 背包?
可能有关 bitset。注意到背包所有元素的和是 O(n)。所以不同大小的个数是 n 的。
不妨二进制拆分做 01 背包,复杂度是 O(1ωnnlogn)
此外,如果有一个儿子大小超过一半,是不用做背包的,这保证了复杂度。
所以树的 siz 是分一半最优,总复杂度可以用主定理计算。
实现的话,需要使用动态大小的 bitset,
可以手写 bitset,或提前开好所有 2k 大小的,用的时候用一个最合适的。
这种问题有关排列,应考虑相对顺序。再转化为背包,应想到 bitset,再观察背包的性质。

CF1764F

连接 (i,j),就意味着把 ij 的路径作为环。fi,j 就是其他点到这个环的距离和。
可以求出每个点的一条出边,也就是若 jf(i,j) 除了 i 以外最大的,那么存在 (i,j)
注意到若 (X,Y) 包含 (x,y) 路径,那么 fX,Y<fx,y
显然,若环的大小越大,那么每个到这个环的距离和就越小。
所以我们可以断言原树的形态是以 f(i,j) 为边权的最大生成树。
当树的结构被确定后,那么边权也很容易。
钦定 1 是根,wi,j=f(i,i)f(i,j)sizj
这种问题要联想到生成树。

CF1827C

关于回文先想到使用 Manacher 算法。
我们借助 CSP2023T2 的算法,设 fi 表示以 i 开头的回文串数量。
fi=1+fjji 右边第一个满足 [i,j] 回文的位置。
问题转化为求右边第一个回文的位置,即求每个位置右边第一个包括它的回文中心。
考虑从左向右扫描,然后每扫到一个回文重心,就更新前面的。
也就是区间取 min,想到可以用吉司机线段树。
然而是不必要的,考虑并查集优化,并查集维护 ri 表示右边第一个还未更新的。
那么直接暴力即可,因为每个点只会被第一次更新。
由于只有一次被更新,所以复杂度是 O(n) 的。
这种问题需考虑 DP,以及并查集优化。

CF1887D

我们发现正面去处理这个问题是很难的。
转化题意,由于有 min 也有 max,枚举其中一个 max
考虑枚举切割点 ai,使得 ai 是左边部分的最大值,且右边都大于 ai
ax 是左边第一个大于 ai 的,那么 x<li
ay 是右边第一个大于 ai 的,azy 后第一个小于 ai 的,那么 yr<z
那么这个问题就很容易地转化为了矩阵加法,可以直接扫描线解决。
那么查询就是单点查询罢了。
这种问题就是需要反方向考虑,之后就是扫描线模型了。

CF1904E

考虑离线询问。
换根 dp,用线段树动态地维护深度,问题转化为最深的点是哪个。
考虑 k 个点带来的限制,即把这 k 个点子树化为 0,用 dfs 序即可,dfs 序是可以换根的。
具体地,可以给这些区间打上一个标记,到时候还原即可。
这种问题首先考虑离线,树上的问题可以换根 dp。

CF1919E

考虑把正数和负数分开来考虑,形成 0-正-0-正-0-负 这样的结构。
正数的话考虑从大往小填数,设 fi,j 是已经填了 i 的数,形成了 j 个连续段的方案数。
当我们加入 i 时,我们对于已经形成的连续段,可以在两边各填一个 i
也可以在两个连续段之间填一个 i,连接这两个段。
注意到一个段如果右端点是 n,那么右边就不用填了。
我们设计状态 fi,j,0/1 表示已经填了 i 的数,j 个连续段,是否出现 n 的方案数。
fi,cij,0fi+1,j,0×Cci1jfi,cij,1fi+1,j,0×Cci1j
fi,cij+1,1fi+1,j,1×Cci1j1,即插板法。
负数同理,最后把正数和负数合并起来即可,同样插板法,把 0 插进去。
这种问题要设计好状态,考虑“插入dp”。

posted @   s1monG  阅读(17)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示