AtCoder Beginner Contest 250 Solution

更好的阅读体验戳此进入

题面链接

题面 Luogu 链接

abc三道题太水了就跳了

[ABC250D] 250-like Number

题面

给定 n,求有多少正整数 k 满足 knk=p×q3,其中 p,q 为质数且 p<q

Solution

看数据范围和题意不难想到,枚举 q。显然 n 的范围在 1018,那么 q 的范围就在 106。或者说 qn13,所以我们先预处理出来 n13 的所有质数,然后枚举每个质数,自然有 pmin(nq3,q1),所以范围内每一个 p 都是合法的。发现这个东西做个前缀和之后即可 O(1) 查询,线性筛素数的话最终就是 O(n13)

Code

[ABC250E] Prefix Equality

题面

给定两个长为 N 的数列 A,BQ 次询问,每次询问给出 xi,yi,求出 A 的前 xi 项去重后是否与 B 的前 yi 项相同。

Solution

水题。最容易想到的是莫队,没什么可说的,但是写着麻烦。

简单思考一下可以想到类似双指针的写法,大概就是对于一个 sumai 一定会对应一段合法的 sumbi,且存在单调性。

然后有个人类智慧的写法就是随便实现一个满足交换律的哈希即可。

Code

[ABC250F] One Fourth

题面

给定凸包,逆时针给定凸包的每个顶点。你需要通过连结两个顶点将凸包划分为两部分并选择其中一个。令凸包面积为 a,选定部分面积为 b,需要最小化 8×|a4b|,求最小值。易证该值为整数。

Solution

发现这东西类似旋转卡壳,于是按照旋转卡壳的思想跑一下,或者说类似在环形上维护一个双指针,固定 l 移动 r,显然我们是想让 8b 尽量和 2a 相同,所以我们在 8b 小于 2a 的时候让 r 一直增大,这样会让面积一直变大,到超过 2a 之后停止,然后移动 l,类似这样跑一下即可,最终复杂度 O(n)

Code

[ABC250G] Stonks

题面

给定序列 Pn 表示 n 天里的股价,每天可以买入或卖出一股,本金无限,求最多能多少钱。

Solution

明显反悔贪心。

不失一般性,令 a<b<c,则若某天存在如下决策,即买 ab,那么赚的钱为 ba,而显然对于 a 来说,若买 ac,那么贡献为 ca>ba,差为 cb,则不难想到当买 ab 的时候再将 b 插入,此时如果存在 c 取了插入的 b,其实际意义即为撤销买 ab 并改为买 ac,但此时 b 天就无操作了,所以我们此时需要再额外插入一个 b,表示后面若需要可以执行一次买 bd 的操作。不难想到可以用小根堆维护,假设堆顶元素为 top,当前元素为 x,若 xtop>0 那么贡献为 xtop,反之将 x 压入小根堆即可。

双倍经验 CF865D Buy Low Sell High

Code

[ABC250Ex] Trespassing Takahashi

题面

给定一张 n 个点 m 条边的无向连通简单图。每条边存在 ai,bi,ci,表示 aibibiai 耗时 ci。给定 k,定义 n 个点中只有前 k 个点有房子,q 次询问,每次给定 x,y,t,求从 xy 连续的不在房子中的时间是否一定会超过 t,超过输出 No,反之输出 Yes。保证询问中 t 满足升序。

Solution

考虑维护对于走每条边时需要多长时间才能连通最近的两个房子,换句话说,满足这个时间的时候这条边就一定可以被走。具体维护可以考虑建一个超级源点并向所有房子连个边,然后跑个 Dijk 即可,当然直接往队列里把所有房子点都塞进去也行。然后我们可以令 cici+disai+disbi 即可,然后显然可以用并查集维护。

具体地,每次询问将边集里所有新的 ci 满足 cit 的边加上,用并查集维护,然后查询一下 x,y 是否连通即可,这个复杂度是 O(mq) 的,当然发现 t 符合升序,所以给边排个序跑一边即可,最终复杂度应该是卡在排序和 Dijk 上,也就是 O(nlogn+mlogm)

同时不难想到即使 t 不符合升序也可以离线排个序再跑,复杂度多个 O(qlogq) 而已。至此本题已经结束,下面是一道加强版的双倍经验。

存在一道双倍经验 CF1253F Cheap Robot,略有区别,这里简单说一下:这道题的区别就在于询问的是最小的 t,这样的话实际上是不太好用刚才的思路离线下来维护的,有一个复杂度不太正确但能过的思路,就是将每个询问的 a,b 分别挂在两个点上,然后将 ci 排序,从小到大依次加边,同时更新所有挂在连通块根上的答案,再对应的把询问合上去。但是这个的并查集一定需要按秩合并,否则如果 clear() 之后 shrink_to_fit() 就会 TLE,否则会 MLE,按秩合并会保证合并询问的时候不会复制太多次以保证空间。这个东西的复杂度理论上似乎可以被卡到 O(mq),但是本题没卡。当然还有一个我口糊的剪枝,就是挂在点上的询问我们用链表维护,然后贪心地取第一次更新这个点时的答案,显然不劣,于是更新后 O(1) 删除即可,但是这个东西理论上也能被卡到 O(mq),不过需要精细设计数据。当然正确的做法最后应该是建出最小生成树然后树剖或者倍增之类的实现。

Code

UPD

update-2022_12_20 初稿