专栏文章

Trick 合集

个人记录参与者 2已保存评论 2

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
2 条
当前快照
1 份
快照标识符
@mioqeu11
此快照首次捕获于
2025/12/02 23:27
3 个月前
此快照最后确认于
2025/12/02 23:27
3 个月前
查看原文
持续更新 ing……

数据结构(Data Structure)

  1. 区间查询操作的结果且为 poly log\text{poly log} 做法时:
    • 如果存在较小量且操作具有结合率:考虑倍增或线段树维护。
      [eJOI 2024] 古迹漫步 / Old Orhei
      题意
      给定一个包含 NN 个节点 MM 条边的有向图(每条边编号为 1M1 \sim M)和一个长度为 TT 的序列 AAAiA_i 表示边编号)。需要处理 QQ 次操作:
      • 查询操作 (1 L R S\texttt{1 L R S}):从节点 SS 出发,依次检查序列 AA 的子区间 [L,R][L,R] 中的每个元素 ZZ。若当前节点 XX 是编号为 ZZ 的边的起点,则移动到该边的终点,否则不动。输出最终停留的节点。
      • 修改操作 (2 i K\texttt{2 i K}):将序列 AA 的第 ii 项修改为 KK
      数据范围:N50N \leq 50M,T,Q105M,T,Q \leq 10^5
      思路
      观察题目中的较小量是什么?不难发现 N50N\le 50。而且,题目中的操作相当于移动点,如果某个点 XX 经过前 kk 次操作到达 YYYY 经过后 kk 次操作到达 ZZ,则 XX 经过总共的 2k2k 次操作会到达 ZZ
      这说明,题目中的操作是满足结合率的。也就是说,线段树是可以合并节点的。对于每个节点,维护 1N1\sim N 每个点经过该节点对应区间后对应的位置。pushup 的时候,直接按上文所说合并即可。
    • 如果不存在较小量且每次操作本质上是合并两个集合(比较罕见):解决方案本质上是使用广义上的 Kruskal 重构树(或者应该叫做 DSU 重构树?),每次合并两个集合的时候,新建节点,并将两个集合的对应节点连接该点。
      这样的好处在于每两个点的 LCA 记录了这两个点最小加入同一集合的时刻。这对维护区间操作结果有很大的作用。
      花田魔法 (flower)
      题意
      给定长度为 nn 的序列 aa,初始 ai=ia_i=i。有 mm 种魔法:
      • xi yi\tt x_i\ y_ii[1,n]ai=xi\forall i \in [1,n]\land a_i=x_iai:=bia_i:=b_i
      接下来有 qq 次询问:
      • l r\texttt{l r}:依次施加第 l,l+1,,rl,l+1,\dots,r 种魔法,序列 aa 有多少个极长颜色连续段。
      例如,aa 序列为 1,1,2,2,31,1,2,2,3,则极长颜色段为 [1,1],[2,2],[3][1,1],[2,2],[3]
      注意: 每次只是假想地施加魔法,并没有真正的进行,即不同询问之间是独立的。
      数据范围: 1n,m,q5×1051\le n,m,q\le 5\times 10^5
      思路
      Hint 1:O(nq)O(nq) 怎么做?
      考虑对极长颜色段拆贡献,转化为 aiai+1a_i\ne a_{i+1}ii 的数量。
      考虑将每次 xiyix_i\to y_i 看作是一条边,每次导致两个集合变为同一个值,也就是合并两个集合。
      于是,每次 DSU 暴力维护即可。查询判断有多少个 iii+1i+1 不在同一个集合。
      Hint 2:如何用 DSU 重构树描述 Hint 1 中的过程
      考虑每次 xix_iyiy_i 合并的时候,新建一个节点,作为 xix_iyiy_i 的父亲,同时另该节点的颜色为 yiy_i。如果不存在颜色 yiy_i,则新建一个节点,作为 xix_i 的父亲。
      注意,这里再表述 xix_iyiy_i 节点的时候,均指最后一次颜色为 xix_iyiy_i 的节点编号。
      这样,在这棵树上,可以很好地通过 LCA 来判断两个点从什么时候开始在同一个集合。
      现在是区间查询,有两个维度(左边界和右边界),扫描线来处理左边界,右边界在 DSU 重构树上处理。
      考虑 llmm11 枚举,每次相当于在树上插入首次操作。这是容易的,只需要新建节点 uu,颜色为 yiy_i,并将 xix_i 的父亲定为 uuyiy_i 的父亲定为 uuuu 的父亲定为原来 yiy_i 的父亲(如果存在)。
      每次只会更新 33 个点,LCA 只会变化 22 个。因为只有 xi,xi+1x_i,x_i+1xi1,xix_i-1,x_i 的 LCA 发生变化。于是,只需要动态维护 LCA,这里由于每次都是改叶子,所以是可以通过倍增数组做到 O(logn)O(\log n) 维护的。

动态规划(Dynamic Programming)

  1. 分步转移:当 DP 维度中存在多个转移互相独立的维度,每次转移时每个维度同时枚举可以转变成仅枚举一个维度,并用 0/1/... 记录已经转移了哪些。
    跳石头 (stone)
    题意
    给定 2×(n+2)2\times (n+2) 的矩形,初始两只脚分别位于第 00 列,终点为两只脚均位于第 n+1n+1 列。
    (i,j)(i,j) 表示左脚在第一排的第 ii 个石头上,右脚在第二排的第 jj 个石头上,那么你可以进行一次跳跃:选择一对整数 (k,l),k>i,l>j,ak=bl(k,l),k>i,l>j,a_k=b_l,然后左脚跳到第 kk 个石头上,右脚跳到第 ll 个石头上,这次跳跃消耗的体力为 (ki)2+(lj)2(k-i)^2+(l-j)^2
    试求从起点到终点最小消耗的体力是多少
    数据范围: n3000n\le 3000
    思路
    fi,jf_{i,j} 表示左脚位于 ii 位置,右脚位于 jj 位置的最小消耗的体力。
    转移枚举下一次的位置 k,lk,l,时间复杂度为 O(n4)O(n^4)
    不过,不难发现题目斜率优化的形式,只不过二维斜率优化是困难的。于是,考虑左脚、右脚实际上是独立的,可以分部转移。从而优化到一维斜率优化。
    时间复杂度 O(n2)O(n^2)

字符串(Strings)

  1. LCP 和 LCS 可以转化为区间最小值:将字符串按字典序排序,则两个字符串 iijj 的 LCP 为 ordiordj\text{ord}_i\sim \text{ord}_{j} 中相邻两个字符串的 LCP 的最小值(LCS 同理)。
    字符串 (string)
    题意
    给定两个字符串 a,ba, b,定义 f(a,b)f(a, b) 为通过以下操作使得 a=ba = b 的最小操作数。如果无法通过操作使它们相同,则 f(a,b)=6666f(a, b) = 6666
    一次操作定义为:选择 aa 或者 bb,选择它的一个子区间 [l,r][l, r],将该子区间的所有字符按字典序从小到大排序。
    现在给定 nn 个长度相等的字符串 s1,s2,,sns_{1}, s_{2}, \cdots, s_{n},请计算出 i=1nj=i+1nf(si,sj)\sum_{i=1}^{n} \sum_{j=i+1}^{n} f(s_{i}, s_{j})
    数据范围: 1n1 \leq nsi5×105|s_i| \leq 5 \times 10^5ns15×105n \cdot |s_1| \leq 5 \times 10^5s1=s2=...=sn|s_1| = |s_2| = ... = |s_n|
    思路
    观察到,f(s,t)f(s, t) 的值仅有 44 种:
    1. s=ts=tf(s,t)=0f(s,t)=0
    2. ss 排序某个区间能变成 ttf(s,t)=1f(s,t)=1
    3. sort(s)sort(t)\text{sort}(s)\ne \text{sort}(t)f(s,t)=6666f(s,t)=6666
    4. otherwise\text{otherwise}f(s,t)=2f(s,t)=2
    考虑将字符串按照 sort(si)\text{sort}(s_i) 排序,那么只需要考虑每个极长相等段即可。
    于是,计算 f(s,t)=1f(s,t)=1 的对数,这样用总数减去 f(s,t)=0f(s,t)=0(容易计算)减去 f(s,t)=1f(s,t)=1 的对数,便是 f(s,t)=2f(s,t)=2 的对数。
    考虑每个字符串 sis_i 的每个单调不降的极长区间 [l,r][l,r],只需要计算有多少个字符串与 ii 的 LCP 大于等于 ll,LCS 大于等于 sir+1|s_i|-r+1
    将 LCP 和 LCS 转化为区间 min\min 之后,不难发现,合法答案在两段区间的交集,将每个字符串变成二元组,这样每次相当于矩阵和。二维偏序,扫描先即可。
    时间复杂度:O(nlogn)O(n\log n)

数学

  1. 整除分块区间 [L,R][L,R] 满足 2LR2L\ge R
  2. 数字 xx1x1\sim \sqrt x 下取整两两不同。

评论

2 条评论,欢迎与作者交流。

正在加载评论...