AT板刷记录
我是彩笔,别人板刷AGC,我板刷ABC和ARC。/fad
ABC379
E - Sum of All Substrings
简单奶龙题。容易想到对每个数字算贡献,以 \(379\) 为例子,贡献分解出来是:
这样一遍循环就能计算出每一位上的数字和,倒过来之后处理进位即可。
F - Buildings 2
如果只有 \(r\),那么就是离线下来单调栈维护就行了。有 \(l\) 的话考虑单调栈中的元素都要大于等于 \(K=\max\limits_{i=l+1}^r a_i\),那么直接一个线段树查询最大值,再二分单调栈中最后一个大于等于 \(K\) 的数的位置,然后没了。有可持久化线段树在线做法。
错因:对单调栈理解不深。
ABC378
E - Mod Sigma Problem
注意到取模只对里面的 \(\sum\) 取,所以不能直接对每个数算贡献。考虑怎么把这个 \(\text{mod}\) 去掉,一般是要将其转化成大小比较的形式。现在只能尝试用前缀和改写和式为:\(\sum\limits_{1\le l\le r\le N}\left( (S_r-S_{l-1})\bmod M \right)\),发现内层的括号是可以去掉的,也就是可以直接对前缀和 \(\bmod M\),得到的结果就是:
发现 \(M\) 的个数就是 \(S\) 中逆序对的个数,剩下的 \(S_i\) 直接分开算贡献即可。
F - Add One Edge 2
显然环的端点在原树上要是二度点,中间点是三度点,那么要找到所有合法的链。考虑从每一个三度点的连通块入手,求出这个三度点连通块连了多少个二度点,贡献就是 \(\frac{cnt\times(cnt-1)}{2}\)。注意要求得到的图是简单图,所以不能算上相邻的二度点。
ABC377
E - Permute K times 2
首先应该想到的是数之间的移动会形成多个环,然后打表观察规律,你会发现第 \(i\) 位在第 \(j\) 次操作后的数就是原来的数在他所在的环上走 \(2^{j-1}\) 步到达的数。于是对 \(k\) 模环的长度就能知道最终的数。
错因:不该直接观察整个数列的变化规律,应该问题精确到具体的数上。
F - Avoid Queen Attack
比EG难。转化成有多少个格子被覆盖,考虑对每个皇后的每个方向的覆盖来讨论,会有很多重复的贡献,可以手动容斥掉,较复杂。
G - Edit to Match
修改末尾的编辑距离,容易想到答案是 \(len_i+len_j-2\times LCP\)。多个字符串,有关前缀,考虑字典树。记录下里每个节点最近的结尾字符的距离 \(f[rt]\),答案就是 \(f[rt]+n-i-1\)。
哈希做法就是对每个串哈希,直接枚举每个前缀对应的最短原串长度就行了,用 umap 维护即可。
错因:脑子笨没想到字典树。想到了哈希做法,但是复杂度想错了,总结为傻逼。
ABC376
E - Max × Sum
考虑按 \(a\) 从小到大排序,钦定最大值就是 \(a_i\),也就是 \((a_i,b_i)\) 是必选的,剩下要选前面 \(k-1\) 个数使得 \(\sum b_i\) 最小,这个可以用优先队列维护。
错因:没想到排序(
G - Treasure Hunting
贪心难题,自己做根本想不到。首先想到一个假贪心:直接每次都选概率最大的点走。这样显然是不对的,但是注意到对于没有先后选择关系的集合而言这个贪心就是对的。考虑能不能转化成若干个集合合并起来的形式,也就是树上的连通块。考虑已经走到了父节点 \(u\),有两个连通块 \(i,j\),记 \(val_i\) 表示遍历连通块的最小期望,\(siz_i\) 是连通块大小,\(p_i\) 是概率之和。如果要 \(i\) 比 \(j\) 先合并到 \(u\) 上,推导出要满足:
于是可以用优先队列维护 \(\frac{siz_i}{p_i}\) 为关键字的连通块,每次合并信息,用个结构体封装一下。
总做法:先想不管先后关系的集合怎么做,然后考虑两个集合合并到答案上的先后关系,最有用优先队列来维护。
错因:没有想到转化成集合合并到答案上的先后关系。
ABC375
E - 3 Team Division
值域较小,考虑设 \(dp[i][j][k]\) 表示前 \(i\) 个人使得 A 组强度为 \(j\),B 组强度为 \(k\) 的最小操作次数。\(j,k\) 的上界是 \(m=\frac{sum}{3}\),转移式很简单,我都能秒,复杂度 \(O(nm^2)\)。
错因:一开始没想到只需要枚举两组的状态就行了。
F - Road Blocked
删边操作不好做,考虑时光倒流转化成加边,每次加边直接 \(O(n^2)\) 枚举每对点更新,具体来讲就是看 \(x\rightarrow u \rightarrow v \rightarrow y\) 还是 \(x \rightarrow v \rightarrow u \rightarrow y\) 还是仍然 \(x\rightarrow y\)。全源最短路直接Floyd预处理就行。
错因:不会时光倒流这个trick。
G - Road Blocked 2
要删边,很容易想到要从 \(1,n\) 都跑一遍最短路,然后判断 \([dis_{1,u}+w+dis_{v,n}=dis_{1,n}]\) 就可以知道这条边是否在某一条最短路上。但是实际上这条边要在每一条最短路上,所以我们考虑维护 \(1,n\) 到每个点的最短路方案数,如果同时满足 \([cnt_{1,u}\times cnt_{v,n}=cnt_{1,n}]\) 那么这条边就是必要的。注意方案数会很大,要对大质数取模。
错因:没想到计算方案数以及不会算方案数以及可以直接取模。
ABC374
E - Sensor Optimization Dilemma 2
最大的最小值,考虑二分答案。然后问题转化成对每个 \(i\) 求这个:两个物品 \(A,B\),买一个价值分别为 \(v1,v2\),代价为 \(w1,w2\),求最少用多少代价达到 \(K\) 价值。做法是枚举 \(A/B\) 的个数小于 \(v2/v1\) 然后直接算,这样相当于把枚举的那个物品当作是较劣的,复杂度 \(O(v1+v2)\)。
错因:不会转化后的做法。
F - Shipping
首先会看出来这是个dp,并且简单贪心想一下可以观察到每次处理的 \(K\) 的订单都是连续的,那么有一个朴素做法设 \(dp[i][j]\) 表示前 \(i\) 个任务在第 \(j\) 天完成的最小代价,转移是在第 \(j\) 天枚举完成的任务段 \([k,i]\)。但是时间是不可能直接作为状态的。
一个优化思路是只保留有用的时间作为状态,发现有意义的时间点一定能表示成 \(t_i+j\times X,j\in[0,i)\)。那么就可以设状态 \(dp[i][j][k]\) 表示前 \(i\) 个任务在 \(t_j+k\times X\) 时间做完。转移考虑填表法,枚举转移到第 \(i+l\) 个任务:
按着转移来就行了。
错因:不会设状态优化。
G - Only One Product Name
显然是转化成图论问题考虑。先 \(O(n^2)\) 枚举 \(i,j\) 如果 \(i\) 第二个字符等于 \(j\) 第一个字符就连一条有向边,最后会出来一个一般有向图,问题转化成有向图最小路径覆盖。有几个注意点,首先图有环,考虑把强连通分量缩点。覆盖的路径可以相交,考虑做一遍传递闭包。然后就是经典模型:拆点,每条边 \((u,v)\) 表示左部的 \(u\) 连向右部的 \(v\),答案是总点数减二分图最大匹配数。
错因:赛时会了做法,但是没写过也不会写,时间也浪费了很多导致没写出来。差点能场切了/ll
ABC373
E - How to Win the Election
排序,考虑对每个人二分额外票数 \(X\)。问题在于怎么计算出剩下 \(K-X\) 分配后有多少个人会比 \(i\) 大。这个不好做,转化成需要多少票使得至少 \(m\) 人比第 \(i\) 个人大。用前缀和辅助处理。具体来说找到需要全部大于 \(a_i+X\) 的区间 \([l,r]\),然后比较将其所有值变成 \(a_i+X+1\) 的代价和能分配给它们的票数的大小。
错因:没有想到转化,硬搞很难。
G - No Cross Matching
智慧题。手画一下可以发现交叉的情况一定会比不交叉的情况下匹配的总距离更大,那么求一组不交的解就可以转化成求距离最小的解。这样就可以直接费用流跑,或者用调整法。
错因:不会转化。
ABC372
E - K-th Largest Connected Components
\(k\le 10\),那么可以直接用优先队列或者 set 维护连通块,然后暴力找到第 \(k\) 大的点。同时显然要采用启发式合并,\(O(n\log n)\)。终于有一道完全独立秒了的。
F - Teleporting Takahashi 2
方案数计数考虑dp。观察这个图的特点,发现没有和多的 \(m\) 条边相连的点只有一条路径可走,于是可以考虑把这些点缩到后面第一个有连边的点上,因为 \(m\le 50\),所以缩点后最多只有 \(100\) 个点,于是我们设 \(dp[u][i]\) 表示走到 \(u\) 点且走了 \(i\) 个点时的方案数,填表法转移:\(dp[v][i]+=dp[u][i-w]\),\(w\) 是缩点后 \(u\) 这一坨的点数。统计答案时注意要考虑走到 \(u\) 连通块内部时得到 \(k\) 步的情况,具体实现是枚举 \(i\in[1,siz_u)\),\(ans+=dp[u][k-i]\)。
错因:没有想到缩点优化状态。但似乎也可以只对 \(m\) 条边进行转移。
ABC371
E - I Hate Sigma Problems
不用扫描线,考虑对每个数计算其贡献,显然要找到这个数的贡献区间,是 \([las_i,n]\),不是 \([las_i,nex_i]\)。贡献就是 \(i\) 左右两边区间长度的乘积。
F - Takahashi in Narrow Road
观察到一次操作后会让一段区间变成公差为 \(1\) 的等差数列,修改成等差数列不好做,考虑对每个 \(a_i\leftarrow a_i-i\),这样子每次修改操作就等于是区间推平操作。如果要将 \([l,r]\) 修改为 \(k\),这次操作对答案的贡献为 \(|\sum\limits_{i=l}^r a_i-k\times(r-l+1)|\)。每次操作通过二分找到 \(l,r\),容易用线段树维护。
ABC370
E - Avoid K Partition
我都会的水题。朴素dp很好写:\(dp_i+=\sum\limits_{j<i} dp_j(sum_i-sum_j\neq k)\),容易把限制条件转化成 \(sum_j\neq sum_i-k\),那么每次的转移就变成了 \(total-\sum\limits_{j<i}dp_j(sum_j=sum_i-k)\),这里可以用一个 map维护,键值为 \(sum_j\),映射为 \(\sum dp_j\)。\(O(n\log n)\) 做完。
F - Cake Division
显然二分答案,但是这是一个环,不好确定以哪一块为起点开始分。首先破环成链,然后记录前缀和,考虑对每个 \(i\) 求出最近的区间和 \(\ge mid\) 的点 \(j\),记为 \(f_{i,0}\) 这个可以双指针得到。因为要分给 \(K\) 个人,所以就是要跳 \(K\) 遍 \(f_{i,0}\),这个就显然是倍增了。这样对每个点倍增求出跳 \(K\) 次后会跳到的点,如果跳到的 \(p>i+n\),那么就是不合法的,这个点就不会被切割。
ABC369
E - Sightseeing Tour
简单题。发现每次询问的 \(k\) 很小,所以考虑直接枚举经过这 \(k\) 条边的顺序,同时也会注意到还需要枚举对于每条边是先走哪个端点。容易想到Floyd预处理两两最短路,遍历顺序枚举完后直接 \(O(k)\) 求出最短路长度。总复杂度 \(O(Qk!2^kk)\),很好写。
F - Gather Coins
简单题。考虑把有值的点按排序,排序后 \(x\) 是单调不降的,于是问题转化成对 \(y\) 求最长不下降子序列的长度,为了输出路径还要记录转移的位置。考虑线段树维护,线段树上的位置代表网格中的第 \(i\) 列的原色,每个元素记录最大的 \(dp\) 值和这个最大值在 \(a\) 中的编号,单点修改区间查询,最后输出路径也简单。
G - As far as possible
首先显然每次选择是在上一次的基础上再选点,每次选择 \(u\) 后都会使答案增加根到 \(u\) 的路径上没走过的边权和 \(\times 2\)。容易想到这就是长链剖分的过程,但我不会,于是考虑简单一点的做法。考虑直接一遍 dfs 把所有最长链都给记录下来,最后直接从大到小增加就行了。这个记录过程具体来说,为了不会算重,每个点子树中的最长链并不要直接记录,而是上传到父亲。其它的链就直接记录下来就行了,随便什么维护都行。
ABC368
E - Train Delay
考虑转化式子,考虑写成填表的形式,令到达 \(a\) 车站的火车为 \(j\),从 \(a\) 出发的火车为 \(i\),要求 \(T_j+X_j\le S_i+X_i\),移项得 \(X_i\ge T_j+X_j-S_j\),为了让 \(X_i\),\(X_i\) 应为 \(\max\limits_{T_j\le S_i}(T_j+X_j)-S_i\)。将火车按 \(S_i\) 升序排序,保证更新顺序正确。这个最大值直接数据结构维护即可,这里对每个车站开一个树状数组,记录 \(\max(T_j+X_j)\),但注意车站编号很大,考虑用 umap 代替数组。
F - Dividing Game
比 E 简单。这个有点像 Nim 游戏,考虑怎么转化。发现选择因数可以看作是取走了多个质因数之积,那么就直接转化成每堆石头的个数是 \(A_i\) 的质因数个数,就是板的 Nim 游戏了。
G - Add and Multiply Queries
比 E 简单。题目告诉你答案不超过 \(10^{18}\),其实就是说 \(b_i>1\) 的个数不会超过 \(60\) 个,因为 \(2^{60}>10^{18}\),只要一直选 \(b_i\) 就一定能达到。知道这点就好做了,考虑用 set 维护 \(b_i>1\) 的 \(i\),同时用线段树维护 \(a_i\) 的区间和,查询枚举在 \([l,r]\) 内的 \(b_i>1\),然后不断假贡献就行了。注意 \(r\) 和最后一个 \(i\) 的边界情况,提前在 set 里塞个 \(n+1\),还有 \(sum\) 在加的过程中也要判断是加上 \(a_i\) 还是乘上 \(b_i\) 更优。
ABC367
E - Permute K times
新trick:对序列元素的置换操作具有结合律,可以用快速幂的方式在 \(O(\log k)\) 次操作中完成。这题就一样的了,不断 \(x_i\),k&1 就更新 \(a_i\)。
F - Rearrange Query
又是新trick:对每个元素随机赋权,比较前缀和判断两端区间的组成元素是否相同。这启示我们对哈希的理解不要局限于只能比较原序列,随机后减少冲突也是哈希思想的一种体现。
ABC366
E - Manhattan Multifocal Ellipse
可以把 \(x,y\) 两部分拆开变成 \(\sum |x-x_i|+\sum |y-y_i|\le D\),这样就能对两部分分开处理。显然 \(-2e6\le x,y\le 2e6\),所以直接枚举坐标为 \(i\),lower_bound 查找其在 \(x\) 中出现的位置记为 \(l\),距离之和 \(dx_i\) 就为 \(i\times(l-1)-pre_{l-1}+suf_l-i\times (n-l+1)\),\(y\) 值同理。记录 \(cnt_i=\sum\limits_{j=-2e6}^{2e6}[dy_j\le i]\),对于每个 \(dx_i\le D\),计算有多少个 \(dy_i\le D-dx_i\),答案即 \(cnt_{d-dx_i}\)。为了减少代码复杂度 \(dx,dy\) 直接开 umap。这个做法是 \(O(V\log n)\) 的能过,但我之前硬写 \(O(V)\) 的预处理没调出来(
F - Maximum Composition
感觉像dp,先无脑设 \(dp[i][j]\) 表示前 \(i\) 个函数取 \(j\) 个的最大值,转移是容易的,但问题在于函数加入的先后顺序也会对答案造成影响。考虑能不能提前排个序解决,我们要比较 \(f_i(f_j(x))\) 和 \(f_j(f_i(x))\) 哪个更优。将函数式化开,都形如 \(A_iA_jx+A_iB_j+B_i\),发现两个式子不同在于 \(A_iB_j+B_i\) 和 \(A_jB_i+B_j\),那么嵌套的顺序可以直接由这两个式子的大小得来。做法也就是我们提前对 \(f\) 数组按 \(A_iB_j+B_i\) 升序排序,这样就能保证答案只和选择的函数方案有关了。
ABC365
E - Xor Sigma Problem
先无脑做异或前缀和。答案明显是所有区间的异或和的和减去 \(\sum A_i\),直接正常求所有区间答案即可。我们的总答案是 \(\sum\limits_{i=0}^{n-1}\sum\limits_{j=i+1}^n sum_j\oplus sum_i\),考虑按位统计答案,这里发现快速求 \(\sum\limits_i sum_j\oplus sum_i\) 更容易。二进制上某一位 \(k\) 能对答案产生贡献,一定是出现一个 \(sum_j\) 的第 \(k\) 位是 \(0/1\) 且前面有 \(sum_i\) 的第 \(k\) 位是 \(1/0\)。于是考虑对每一位记录多少个 \(sum_i\) 的第 \(k\) 位为 \(0/1\),记为 \(f_{k,0/1}\)。这样枚举到 \(sum_j\) 的第 \(k\) 位的贡献就是 f[k][(bool)((1ll<<k)&sum[j])^1]*(1ll<<k),同时更新 \(f\) 就完了。
G - AtCoder Office
\(n\) 个人平分 \(m\) 次操作,有人多有人少,考虑记录下每个人的操作然后根号分治处理。如果一个人 \(i\) 的操作次数 \(\ge B\),那么预处理他对其他人的答案,实现方法是直接枚举另一个人 \(j\) 和它的第 \(k\) 次操作(让他在室内),然后提前前缀和得到 \(i\) 在这段时间中的停留时间。稍微分析一下可以得到这一块的复杂度是 \(O((n+m)\sqrt{m})\) 的。
查询时如果 \(x,y\) 中有一个人与处理了答案就直接输出,否则两个人的操作次数都 \(\le B\),那么这样直接暴力双指针就能求得答案,\(O(q\sqrt{m})\)。

浙公网安备 33010602011771号