LG-P6157 有趣的游戏 Solution

更好的阅读体验戳此进入

题面

给定 n 个点的树,存在点权 wi,独立询问每次可能为单点修改点权,可能给出两点,A 在树上两点最短路径上选择两个点 x,y 最大化 wxmodwy,后者在树上选择非 x,y 的两点同样最大化上式,对于每次询问求出 A 最大的值,并求出此时 B 最大的值,A 无法选择则输出 -1

Solution

提供一种复杂度正确但常数巨大码量较大并不优秀的无脑做法,思路来自于模拟赛赛时口糊的,在 Luogu 上可以通过,但赛时在 LemonLime 测的时候大概是因为常数原因被卡的就剩 20pts

首先我们不难想到 wxmodwy 即为链上次小值。这个不难证明,若我们选择最大值,那么其对较小值取模后一定小于较小值,而若我们选择次大值对最大值取模那么可以直接保留次小值。

然后呢最开始我看这道题没太仔细,以为 B 也是在链上找,于是考虑的是维护次次小和次次次小保留次次次小,当然这个是大错特错的,不仅没有考虑 B 是树上的,还没有考虑 A 不能重复权值但 B 可以。

于是在我发现问题后就尝试优化这个思路,最终的过程大概是这样的:

首先树剖显然,然后线段树上维护区间的不可重复的前 5 大值,以及最多重复一次(即有两个)的前 5 大值。然后对于合并子区间,我们考虑直接维护结构体然后重载 +,实现上用一个 basic_string 存子节点所有值然后排序并各种特判细节做一下即可,不难发现超大的常数就是卡在这里了,这东西某种意义上来讲可以认为其为 O(1) 的,但是实际上个人感觉平均大概有个 10 左右的常数。

然后修改较为简单不再赘述,对于查询直接按照树剖查询并合并,对于不能重复的前 5 大取其第二大作为 A 的答案,不存在则输出 -1。然后我们要再次查询整棵树的结果,在可重复两次的前 5 大中删去 A 的两个答案,此时不难理解为什么维护的是可以重复两次的。然后此时还需要分类讨论,如果结果不够说明只能找到两个相同的数,这样结果为 0,如果最终剩下三个数且前两个为 0,那么说明原来的为 a>b>c=d>e,然后 a,b 被删除,此时如果我们不维护 e 答案将变为 0,这也就是为什么我们要维护前 5 大而不是 4,显然此时答案应为 e。同时因为题里没有说 B 取不了的情况,且不难想到只要 n4 那么 B 一定可以拿,所以姑且可以认为题目保证了 n4

当然这里也浅提一下,如果用 multiset 维护 B 的话就只需要维护最大和次大就可以了,常数小且好写,也不知道我模拟赛的时候为什么没想到,估计是开始读错题之后先入为主了。

Code

UPD

update-2023_01_17 初稿