// 鼠标点击特效 //

Codeforces Round 1051 (Div. 2)

A

关键性质是题目给出的序列是排列。那么我们可以知道,想要最终序列归零,一定有第 \(i\) 次操作的区间值域为 \([i,n]\) ,否则无解。

我们只需要判断,对于每一个 \(1 \leq i \leq n\) ,是否存在一个区间值域连续且恰好为 \([i,n]\) 即可。时间复杂度根据实现方式在 \(O(Tn^2)\)\(O(Tn)\) 之间,不过都可以通过。

B

先将 \(a\) 排序。我们希望尽可能的将比较贵重的物品免单,所以每一次选择 \(b_i\) 最小的优惠券,用于最贵的 \(b_i\) 个物品即可。

时间复杂度为 \(O(Tn \log n)\) ,瓶颈在于排序。

C

根据样例,我们猜测每一条边的贡献都可以取到 \(\max\{x,y\}\) 。接下来给出一个简单的构造:

  • 对于每一条边,如果 \(x>y\) 则让 \(u\) 连向 \(v\) ;否则 \(v\) 连向 \(u\) 。那么一定会得到一个DAG。
  • 获取DAG的一个拓扑序,一个元素在拓扑序中越靠前,\(p\) 越大。

容易发现这是满足条件的。时间复杂度 \(O(Tn)\)

D

题目对于序列的限制为:

  • 逆序对之间连边,是一张二分图。

这个限制应该比较经典,有经验的选手知道这等价于序列可以被划分为两条非下降子序列(可空)。接下来简单讲解一下为什么:

二分图不存在奇环,我们找到某种很小的子结构但是存在奇环:\(i<j<k\) 但是满足 \(a_i>a_j>a_k\) 。我们发现,如果不存在这种子结构,显然是合法的序列。也就是,最长下降子序列长度至多为 \(2\) ,根据序理论的一套知识,这等价于可以被划分为两条非下降子序列。

那么可以开始 dp 了。定义 \(f_{i,j}\) 表示,考虑了序列的前 \(i\) 个元素,提取出的子序列被划分出的两个非降子序列中,一个的结尾为 \(a_i\) ,另一个的最小结尾为 \(a_j\) 。我们如何定义最小结尾呢?就是在某一条非下降子序列末尾为 \(i\) 的前提下,另一条子序列的末尾最小是多少(以权值为第一关键字,下标为第二关键字)。因为这样才可以尽可能的接上下一个元素。特别的,\(j=0\) 表示另一个子序列为空。

转移可以分类讨论一下:

\(f_{i,0}\) 的转移:只能枚举一个前驱 \(j\)\(a_{j} \leq a_i\),从 \(f_{j,0}\) 转移过来。

\(f_{i,j}\)\(a_j \leq a_i\) 的转移:

  • \(f_{k,j}\) 转移过来。说明 \(a_i\) 接在了 \(a_k\) 的后面,就有 \(a_k \leq a_i\) 。但是我们并没有从 \(j\) 接过来的原因一定是 \(k\)\(j\) 更大,就还有 \(a_k \geq a_j\)

  • \(f_{j,k}\) 转移过来。说明 \(a_i\) 接在了 \(a_k\) 的后面,就有 \(a_k \leq a_i\) 。但是我们并没有从 \(j\) 接过来的原因一定是 \(k\)\(j\) 更大,就还有 \(a_k > a_j\)

\(f_{i,j}\)\(a_j>a_i\) 的转移:

  • 不论是从 \(f_{j,k}\) 还是从 \(f_{k,j}\) 转移过来,一定是不可能把 \(i\) 接在 \(j\) 后面的,只能接在 \(k\) 后面。则只需要满足 \(a_k \leq a_i\) 即可。

  • \(dp_{j,0}\) 转移过来也可以。

暴力转移是 \(O(Tn^3)\) 的。可以通过 D1 。
不过转移可以使用线段树/树状数组做区间求和优化,做到 \(O(Tn^2 \log n)\) 。可以通过 D2 。

E

疑似本场最难题。

操作是可逆的,所以我们先将 \(s\) 变换为一种十分优秀的形态,不会对答案的结果产生改变。

如果出现了连续的两个相同的括号,这两个括号可以作为一个整体任意移动。拿 \(((\) 举例:

  • 对于结构 \()((\) ,可以通过如下操作交换位置:\()(( \rightarrow ))) \rightarrow (()\)
  • 对于结构 \((()\) ,可以通过如下操作交换位置:\((() \rightarrow ))) \rightarrow )((\)
  • 对于结构 \((((\) ,可以不操作,但是认为交换了位置。

所以说,我们可以把上述结构先删了备用,最后插入到任意位置。那么,最终得到的字符串一定只有如下三种形式:

  • 空串。
  • \()()() \dots ()()(\)
  • \(()() \dots ()()\)

假设提取出了 \(x\) 个连续两个相同括号的子结构。

  • 如果 \(x\) 是奇数,肯定是无解的。
  • 如果 \(x\) 是偶数,就有 \(x\) 是否等于 \(0\) 的区别。当 \(x=0\) 时,第二种情况是无解的,不过第一,第三种情况都是有解的。当 \(x>0\) 时,上述三种情况都是有解的。具体构造就是:将 \(\frac{x}{2}\)\(((\) 放在串开头,将 \(\frac{x}{2}\)\())\) 放在串结尾。

时间复杂度 \(O(Tn)\) 。做法很简单,不过是 Ad-hoc 。

F

什么样的序列可以被获取呢?我们按照下标从大到小构造,\(a_i\) 的取值就是 \(a_1,a_2 \dots a_i\) 所构成的线性基可以组成的任意元素。

那么序列可以被划分为至多 \(\log V\) 段,每一段 \([l_i,r_i]\) 表示 \(a_1,a_2,\dots,a_{p-1},a_{p}(l \leq p \leq r)\) 所构成的线性基都是相同的。那么有无解判断就只需要模拟一遍:初值 \(v=-inf\) ,然后遍历第一个线性基段,找到线性基中比 \(v\) 大的第 \(r_i-l_i+1\) 个元素,用它来更新 \(v\) 。直到遍历所有段,如果中途出现了线性基大小不够的情况无解。这个贪心的正确性显然,因为每时每刻我们都尽可能让末尾最小。

上述操作中,会用到线性基第 \(k\) 大,和线性基求 \(x\) 的排名。一个线性基在经过 \(O(\log^2 V)\) 预处理的情况下上述问题单次回答可以做到 \(O(\log V)\) 。这个是基础知识,不多赘述了。

现在只需要对于每一个后缀 \([i,n]\) ,维护出上述的线性基段即可。发现这是很好维护的,考虑增量维护。添加 \(a_i\) 就将 \([i+1,n]\) 这个后缀的线性基段全部插入 \(a_i\) ,再新增一个只有 \(a_i\) 的线性基。最终去重即可。

时间复杂度根据实现在 \(O(Tn \log^2 V)\)\(O(T n \log^3 V)\) 之间。不过都是可以通过的。

posted @ 2025-09-18 10:07  dan-da-dan  阅读(50)  评论(1)    收藏  举报