OI 训练日志
CF1804F(×2700)
令 \(x,y\) 为直径两端,则 \(\forall u\) 有 \(\rho(u,x)+\rho(u,y) \ge \rho(x,y)\),即 \(\max(\rho(u,x),\rho(u,y)) \ge \frac {\rho(x,y)} {2}\)。根据这个性质,可随意设定源点 \(s\),求出 \(x=\{\max_{u} {\rho(s,u)}\}\),则直径长度在 \([x,2x]\) 中。
在动态加边过程中维护 \(x\) 是不现实的,那怎么办呢?注意到回答任意 \([x,2x]\) 中的数均合法,且其中至少含一个二的幂次,于是回答 \(\ge x\) 的最小二的幂次即可。注意到只有 \(O(\log n)\) 种可能的答案,且加边过程中 \(x\) 单调不增,对于每种可能的答案 \(s\),二分 + bfs 求出 \(x \le s\) 的最初时刻即可。时间复杂度 \(O((n+m) \log n \log q)\)。
这题启发我们,Codeforces 禁止 Hack 不仅可能是因为随机化,也可能是 SPJ 的复杂度过劣。据说用云服务器跑出正确答案用了若干天,比较震撼。
CF1764H(×3400)
先断环为链,然后倒着扫描线,令 \(f_i\) 表示元素 \(i\) 能存活至什么时刻。若在 \(t\) 时刻对 \((l,r)\) 操作,则 \(\forall i \in (l,r])\),\(f_l\) 应对 \(f_i\) 取 \(\max\) 并将 \(f_i\) 改为 \(t\)。
注意到,\(f\) 只会被区间摊,单点修。根据经典套路,使用 set 维护 \(f\) 的每个连续段,树状数组维护桶即可。时间复杂度 \(O(n \log n)\)。
CF1801G(×3400)
为方便叙述,称 \(t[a,b]\) 合法,当且仅当 \(\exist s_i = t[a,b]\)。
将对 \(t[l,r]\) 的询问拆成三部分:
- 求 \(1 \le a \le b \le r\) 的合法 \([a,b]\) 个数 \(A\)。
- 求 \(1 \le a \le b < l\) 的合法 \([a,b]\) 个数 \(B\)。
- 求 \(1 \le a < l \le b \le r\) 的合法 \([a,b]\) 个数 \(C\)。
- 答案即 \(A-B-C\)。
\(A,B\) 的计算是平凡的:对各 \(s\) 建出 AC 自动机,对 \(s\) 的各段前缀在 fail 树上定位,算出祖先中 endpos 数量并求和,复杂度线性。
考虑 \(C\) 的计算。对各 \(s\) 的反串同时建出 AC 自动机,将 \(s[1,l-1]\) 在正串两自动机上定位,将 \(s[l,n]\) 在反转自动机上定位,并倍增跳直到串长 \(\le r-l+1\)。问题转化为:给定 \(x,y\),求 \(x,y\) 的祖先中有多少相对应的节点。离线下来 dfs,使用树状数组维护另一棵树的信息即可,时间复杂度线性对数。
若强制在线,使用标记永久化主席树维护信息即可,复杂度也是线对。
「DTOI-4」中位数
二分答案,转化为判断中位数是否能 \(\ge \alpha\)。令 \(b_i=[a_i < \alpha]\),则 \([l,r]\) 的中位数 \(\ge \alpha\),当且仅当 \([l,r]\) 中 \(1\) 的数量 \(>\) \(0\) 的数量,此时可将 \([l,r]\) 全改为 \(1\)。
观察到,操作次数 \(\le \log_2 n\),且操作的区间逐渐向两头扩展。考虑迭代 \(\log n\) 轮,第 \(i\) 轮对所有 \(j \in [1,n]\) 计算出 \(L_{i,j}\),表示左端点最远能延伸到的位置,使得操作次数 \(\le i\)。将 \(L\) 各位置改为后缀最小值,然后扫一遍,用单调栈维护关键点,每次二分即可,时间复杂度 \(O(n \log^3 n)\)。
更进一步的,注意到:令 \(pre_i\) 表示 \([1,i]\) 所有元素 \((1 \to 1, 0 \to -1)\) 的和,那么只用考虑 \(pre_i\) 的后缀最大值。这样一来,每次可以直接弹栈,不需二分。可能和线性复杂度的斜率优化比较像。复杂度 \(O(n \log^2 n)\)。
AGC022E
容易将操作转化为:
- 选择三个连续的 \(0\),将
000整体替换为0。 - 选择一对相邻的 \(0,1\),将它们同时删去。
- 目标:串中不存在 \(0\)。
先考虑判定。维护一个栈,表示目前未被消去的元素,其由一段连续的 \(1\) 和一段连续的 \(0\) 构成。
咕咕咕。

浙公网安备 33010602011771号