CG#1G
题意:给出一棵 (N(leq 5 imes 10^5)) 个点的树,有些点已经被染成白色。甲乙两人博弈,甲每次把一个没染过的点染成白色,乙染黑色,甲先操作。任意时刻,如果出现一条同色的三个点的链,该颜色方就胜利。若双方都执最优策略,判断胜负或平局。
题解:如果有度数为 (4) 的点,白方第一步就可以选那个点,必胜。类似地,如果存在一个度数为 (3) 的点,且它有两个支链长度至少为 (2)(黑方一次只能堵住一个),白方依然必胜。由该结论得到推论:如果有至少 (3) 个度数为 (3) 的点,白方必胜。现讨论图里有几个度数为 (3) 的点。
① (2) 个,记为 (p) 和 (q)。由上述结论,除了中间一条长链,(p) 和 (q) 另外两侧的支链必然只有一个点(否则白方胜)。而且,如果图中至少有一个白色点已经涂好,也必然白方胜。注意此时不一定是平局,还要观察中间长链的奇偶性。
② (1) 个,记为 (p)。显然 (p) 除了一条长链连出去,另外两侧必然只有一个点。如果无任何初始白点则平局(白方每走一步,黑方贴着它左边下)。如果有一个不在长链末端的白点则白方胜;否则要判断长链的奇偶性。
③ (0) 个。就是一条链。位于中间的已经染过的白色格子,或者存在距离差为偶数的两个白色格子都是白方赢,否则平局。
CR#534B
题意:交互题。要猜出一个未知正整数 (a(1 leq a leq 10^9))。每次给judge两个数 (x) 和 (y),返回 (x mod a geq y mod a) 是否成立。最多进行 (60) 次这样的操作。
题解:如果我们询问一组 ((t,2t)),考察会出现怎样的结果:当 (t<a<2t) 时必然不成立,当 (t geq 2t) 时必然成立,其余情况不确定。我们想借助后面两个条件来二分,所以会要求先估计出 (a) 的一个下界。
有 (60) 次操作限制,所以还能再进行一次类似于二分的操作。我们可以先从小到大询问 ((2^k,2^{k+1})),找到第一个不成立的区间:这时候就确定了,(a) 必然落在区间 ((2^k,2^{k+1}])。然后再对 (a) 直接二分。稍作修改,每次询问 ((2^k,mid)),即可确定二分方向。
CR#534C
题意:给出一个每个点度数至少是 (3) 的简单连通图。读入 (K(K leq N leq 2 imes 10^5)),或者找到一个长度至少为 (frac{N}{K}) 的简单路,或者找到 (K) 个环,满足:①环长至少都是 (3)。②环长不能是 (3) 的倍数。③每个环里至少要有一个点不在别的找到的环里(我们称之为代表点)。
题解:只要利用上题目中的古怪条件和限制就能出解。首先,简单路是十分Hard的,所以必然是 DFS 式地找简单路,并搜出一棵生成树。如果没有达到第一个要求,那么我们搜出的生成树高度 (<frac{N}{K}),即至少有 (K) 个叶子。这和要求的环的数量吻合,所以尝试把这些叶子作为代表点去找那 (K) 个环。因为每个点度数至少为 (3),所以叶子至少有两条不同的返祖边,它们会形成 (3) 个环。鸽笼原理,必然有一个环长不是 (3) 的倍数且至少为 (3) 的环。
CR#534D
题意:给出 (N(leq 10^6)) 个正整数 (a_i(leq 10^{12}))。可以选择一些数,除掉一个自己的约数 (d_i(d_i | a_i))(且满足 (d_i leq K))。每一个数还有一个修改代价 (p_i)。对于你选择修改的数的集合 (S),总代价为 (|S| imes sum limits_{i in S} p_i)。要使得所有数的GCD为1,求最小总代价。
题解:将初始的 GCD 质因数分解,不同质因子个数 (m leq 11)。显然,我们最终目的是将这 (m) 个质因子划成一些集合,每一个集合对应一个数(同时要符合 (k) 的要求),使得 “集合数 ( imes) 代价和”最小。
将 (a_i) 对这 (m) 个质因子分解,得到一些 (m) 维向量。 完全相同的向量最多只需保留代价最小的 (m) 个。
标程的做法是,直接暴力枚举所有合法的划分。每个集合要配一个不同的数,所以要预处理能覆盖集合 (S) 的代价前 (m) 优的数字,然后把这些集合和它们拓展出来的这些数字做一个匹配。每次匹配是,左侧最多 (x) 个点((x) 为集合数),右侧最多 (x^2) 个点,单次复杂度 (O(x^3)),总复杂度 (sim 10^8)
还有一个 DP 解法。设 (f_{i,j}) 为:现在覆盖了集合 (i),且正好选了 (j) 个集合的最小代价和。把可能成为答案的向量都丢进去 DP 一遍。我觉得复杂度存疑。
CR#532F
题意:给出 (N(leq 5 imes 10^5)) 个数和 (Q(leq 5 imes 10^5)) 个询问,每次给你 ((l,r)),问 (l sim r) 这些数里选一些异或能凑出的最大的数是多少。51nod 1577原题。
题解:显然是区间提取线性基。线段树暴力是 (O(N log^3 N)) 的,采用优美的 CDQ 分治可以做到 (O(N log^2 N))。
有一种比较玄学的 (O(N log N)) 解法。对于一个区间的结束位置 (r),维护 (1 sim r) 的线性基,而且它是由最靠后的这些数字构造出来的。具体地,每次插入 (a_r) 时,从大到小枚举有 (1) 的每一位:如果该位为空,插入并退出;否则,选择位置靠后的数字放入,剩下的数字消掉这一位后继续往前循环。
为什么要这么维护呢?对于一个有端点 (=r) 的询问,取线性基里所有位置 (geq l) 的数字出来,即是关于它的线性基。基于此直接询问即可。
ECR#58F
题意:有 (N(leq 400)) 个城市,第 (i) 个城市位于 (a_i(leq 10^9)) 公里处。 有 (M(leq 250000)) 辆卡车在运输,第 (i) 辆车要从城市 (s_i) 到 (t_i),每公里耗油 (c_i),且最多能在沿途经过的城市加油 (k_i) 次(每次加满)。设计一个全局卡车的最小油箱容量使得所有限制都被满足。
题解:一种直观的想法是二分答案,然后就掉进死胡同了……其实可以直接算出每个卡车的最小要求取个 max 的。
因为 (N) 比较小,考虑对城市进行 DP。限制很多,而且 (c_i) 彼此不一样,所以要把和路程有关的量放在 dp 数组的值里。枚举每一个起点 (s),设 (dp_{i,j}) 表示从 (s) 到 (i),最多能加 (j) 次油的情况下,最小的可行油箱容量。该 DP 可以通过单调性 (O(N^2)) 预处理出。然后跑一遍相同起点的限制算一算即可,总复杂度 (O(N(N^2+M)))。
ECR#58G
题意:给出 (N(leq 2 imes 10^5)) 个数。将它们划成一些连续的段,每一段的值为这一段数字的异或和。对于一种划分方案,如果不存在异或和为 (0) 的段的集合,则称之为合法划分。求合法划分最多能划成几段。
题解:显然是线性基相关的题。一个很重要的发现是,每个段自身的异或和 (xor_1,xor_2,dots) 构成的线性空间,等价于前缀异或和 (sum_1,sum_2,dots) 构成的线性空间。(sum_n) 必须选,然后就只要从后往前扫描,每次把 (sum_i) 丢进去,如果不能消掉,就选上这一段。复杂度 (O(N log N))。
CR#530C
题意:构造一个 (N(leq 10^5)) 个点、每个点深度之和为 (S(leq 10^{10})) 的树,要求度数最小。
题解:对于固定的 (N) 最大度数 (d),能构出的树的 (S) 是一段连续的区间。所以我们可以直接确定出最小度数 (d)。构造的时候,我采用逐层构造。在每一层,放了(确定了)若干个点后,剩下能构造出的 (S) 也是一段连续的区间,而且这些区间是有单调性的。所以每次二分放多少个点,继续往下构造即可。
CR#530D
题意: 每次选择两个数 ((a,b)(a leq b)) 合并成 (a+b),这样 (N) 个数合并 (N-1) 次后就只剩下一个数了。合并过程中,每出现 (b leq 2a) 的情况,不确定值就加一。现在有 (T(leq 5 imes 10^5)) 个操作,每次加入一个数或者删除一个数,或者问当前数字集合的所有合并方案中,不确定值之和最大可能是多少。
题解:比较传统的套路题?不加证明地猜想,每次挑最小的两个数合并会使得不确定值之和最大。但是哈夫曼树是不能动态维护的。手画一些例子发现很难出现 (b > 2a) 的情况。将原数组排序后,显然 (2sum limits_{i=1}^{k-1} a_i < a_k) 是 (b > 2a) 的充分条件;其实这也是必要条件。考虑直接用权值线段树来维护这些操作。每次暴力累加一段前缀的和 (x),然后线段树里寻找第一个大于等于 (2x+1) 的数。每次至少扩大两倍,总复杂度 (O(N log^2 N))。
Hello 2019 D
题意: 黑板上写了一个数 (N(leq 10^15)),操作 (K(leq 10000)) 次,每次将其等概率变成它的一个因数。问最后留在黑板上的数的期望。
题解: 很old的题了。一个显然但是重要的结论是:各质因子之间独立。每个质因子计算时只要考虑质数就行。对于每一个质因子直接 (O(Kc)) DP即可,总复杂度就是 (O(K log N))。也可以一开始全都预处理好,设 (f_{i,u,v}) 表示 (u) 经过 (i) 轮到了 (v) 的概率,可以用前缀和优化成 (O(K log^2 N))。
Hello 2019 F
题意:维护 (N(leq 10^5)) 个可重集,一共有 (Q(10^6)) 个操作。①将第 (i) 个可重集设置为只有一个元素 (v) 的集合。②将第 (i) 个集合设置为第 (j) 个和第 (k) 个的并。③将第 (i) 个集合设置为第 (j) 个和第 (k) 个的乘。定义乘操作为:(forall x in S_j,forall y in S_k,(x,y) in S_i)。④询问元素 (v) 在第 (i) 个集合里出现了奇数次还是偶数次。 (v leq 7000)。
题解:一看数据范围就是 (bitset) 乱搞的题。因为是问奇偶性,容易发现,只要维护可重集里每个数是否出现了奇数次。③ 操作看起来十分难维护。从集合反演那套理论中获得启发,尝试将集合转化成“另一种形式”来维护。gcd和因数有很大的关联,对于①操作,考虑将所有 (v) 的因数标为 (1),观察是否能维护;即,用 (F_x=sum limits_{x|y} S_y) 来表示集合 (S)。惊奇地发现,③ 操作可以直接用 (F_x cap F_y) 来快速维护。而 ② 操作依然是简单的 (oplus) 操作。至于询问的话,可以直接预处理莫比乌斯函数,也表示成 (bitset) 形式,就可以做到快速询问了。总复杂度 (O(frac{QV}{32}))。
Hello 2019 G
题意:给出一个 (N(leq 10^5)) 个点的树,一共有 (2^N) 种点集选取方案。设 (f(S)) 为,在树上将点集 (S) 连起来需要用到的边的数量。求 (sum f(S)^K)。(K leq 200)。
题解:先考虑暴力 DP,用一个长度为 (K+1) 的数组,来维护当前所有方案的 (0,1,dots,K) 次方的和。在原树上 (DP),设 (f_{x}) 表示 (x) 子树里至少选择一个点的方案数组。为什么要至少选一个点呢?这样就要强制往上连边了。对于一种点集选取方案,在它们的 (LCA) 处统计答案。很容易设计出一个 (O(NK^2)) 的做法(会出现两个方案数组关于组合数卷积的操作)。
这种 (K) 次方的题,肯定是用第二类斯特林数优化。尝试将方案数组的结构改一改。本来的意义是:第 (i) 个数是所有方案的 (i) 次方之和;现在的意义是:第 (i) 个数是 (sum C_{x}^(i))((x) 是所有方案的值)。一般斯特林数优化的题只会出现答案整体加一的情况,这样新的方案数组可以类似于组合数的转移,复杂度从 (O(K^2)) 降为 (O(K))。
但此题中,会出现两组答案合并(左右两个集合里的方案两两组合构成新的答案)的情况。一般的,我们有: (sum limits_{u} sum limits_{v} C_{u+v}^k=sum limits_{i=0}^k [sum limits_{u} C_u^i] imes [sum limits_{v} C_v^{k-i}]) (考虑组合数实际意义即可证明)。所以依然可以用卷积的方式来合并。
问题是:现在的合并复杂度依然是 (O(K^2)) !注意到本题是在树上做,是有特殊性质的。对于一个子树大小为 (size_x(size_x leq K)) 的子树,它内部点集无论怎么选,边最多 (size_x-1) 条,所以方案数组 (geq size_x) 的位置必然是 (0)。我们可以用树形背包的经典 (trick),每次只 (for) 到 (min(size_x,K)),复杂度就能变成 (O(NK))。