猪猪侠再战括号序列
算法一
有一个超良心测试点满足
算法二
算法一显然太无脑了。考虑翻转操作其实用起来非常不爽,因为牵连的元素个数太多。如果题目允许你每次交换序列中的两个元素的位置,那么其实要好办很多。
于是我们重新设定目标,把目标序列变为一个显然是合法的括号序列,类似这样 “(((())))”。
我们从左往右依次处理原序列的前
暴力在右边找左括号,然后再暴力翻转序列就能做到
算法三
对于算法二,用 splay 维护括号序列找左括号以及翻转就能做到
算法四
好吧其实自己手玩下就清楚了。我们不要“随便找个左括号”,我们就找当前位置右边的第一个左括号。那么当前位置到那个左括号之前肯定都是右括号,翻转过来也就只有两端变了。
好那么怎么找第一个左括号呢?显然第一个左括号的位置只可能越来越靠右,所以在上一次找到的左括号的位置基础上继续往右走就行了。
时间复杂度
另外我题目中说的是
跳蚤公路
算法一
题目中说超过
对于第 1 个测试点数据范围非常小。一个比较容易发现的事实是如果存在负权环,那么一定存在简单负权环(即不经过重复的结点)。于是我们用最暴力的方法搜索出图中所有的简单环,对每个简单环求出
然后我们对于每个结点找出所有
要请各位注意的是 C++ 中 -10 / 3 = -3
,是向零取整。因为这个被坑的同学恭喜了。
算法二
什么?你说你写不清楚找简单环?没关系,如果你裹得清楚这个算法的其余的部分还是可以得分的!看 6 号测试点,所有的简单环都是自环。做掉这个测试点就能获得
算法三
到这里我们发现基本思路就是找简单环列不等式。但是简单环个数肯定不会少,所以我们要减少需要考虑的简单环数目。
如前所述,对于每个简单环有个
于是我们可以使用 Floyd。我们在 Floyd 的基础上多加一维记录
后面的部分与算法一相同。可以通过前 5 个测试点获得 50 分。结合算法二能获得 60 分。
算法四
下面来说正解了,这题其实有多种算法。
首先我们刚才玩了那么大一圈最后陷入的 Floyd 的不归路导致无法继续优化。让我们来想想,如果
我们考虑传统的Bellman的大概思想,就是
好,但是这仅仅只是图中有负环而已,我们还得知道这个负环会牵连哪些结点。我们就找出
利用这个想法我们可以很简单地拓展为
把
时间复杂度
为了方便数学弱的小白我们多说几句,怎么解那个不等式呢?一定是对于所有的
对于每个固定的
于是现在只剩初中数学难度了。
其他算法
好吧我们来讲其他做法。其实仔细思考下 6 号测试点的深层含义,摆明了一副得DAG者得天下嘛。我们可以找到所有的强连通分量缩起来。要知道,只有强连通分量里有可能出现环,而且强连通分量里一旦出现负环,每个强连通分量内的点都可以走到负环再走回来。这意味着强连通分量内每个点的可行
而判断一个强连通分量内负环的取值范围,我们只用建一个超级源点向所有点连权值为
(可能有人会问为何要建一个超级源,用强连通分量中任意一个点不行么?当然不行。比如某个点走到负环上需要走
UPD:(上面这个算法是错的……T_T……大家还是写算法四吧,质量有保障)
当然了,由于一个环永远只是贡献一个一次不等式,所以
树上GCD
算法一
枚举两个点
当然你也可以枚举 LCA,然后往子树方向进行 bfs,由于计算 gcd 是
可以获得 10 分。
算法二
随机生成的树的树高为
枚举
于是总复杂度
算法三
我们可以把问题转化为,对于每个
第4个数据点中,从根结点挂下来若干条链,长度分别为
复杂度
算法四
考虑点分治,每次取出当前树的中心
均在 的子树内,此时 LCA 即为 。和算法三类似,只是第 条链中高度为 的倍数的点的数量需要在处理出 数组后花 的时间统计,所以复杂度是 。 在 的子树内,而 不在。我们把当前树的根节点记为 , 到 的路径为 。记 下面的子树高度为 , 旁边伸出的子树(即不包含 的)的高度为 。枚举 ,那么 位于 旁边的子树中,然后我们仍然枚举 ,用 的时间求出 子树中高度为 的倍数的结点数量;但我们还需要知道 的子树中有多少点相对于 的高度是 的倍数,也就是说我们要在 子树的 数组中查询下标间隔为 的子序列中的元素之和。注意到间隔为 时,至多只有 种这样的子序列,我们对重复查询进行记忆化。于是对于 ,查询的复杂度不超过 ,总共是 ;对于 ,单次查询的复杂度为 。
所以一层分治的复杂度是
见:http://uoj.ac/submission/2785
第二步如果使用比较暴力的方法还是可以通过 5 号测试点的。
其他算法
其实这题也可以用启发式合并做。我们还是可以用容斥转化为求
对于