2019 Multi-University Training Contest 10

Contest Info


[Practice Link](https://cn.vjudge.net/contest/322368#overview)
Solved A B C D E F G H I J K
7/11 - - O Ø O - Ø O O - O
  • O 在比赛中通过
  • Ø 赛后通过
  • ! 尝试了但是失败了
  • - 没有尝试

Solutions


C - Valentine's Day

题意:
\(n\)个礼物,每件礼物能让你女朋友开心的概率是\(p_i\)
现在你可以选择\(k\)件物品,\(k\)由你自己定,但是你要让你女朋友恰好开心一次的概率最高。

思路:
设已经购买的礼物一次都不能让女朋友开心的概率为\(s_0\),恰好开心一次的概率为\(s_1\),再买一个概率为\(p\)的礼物会使得:

\[\begin{eqnarray*} (s_0, s_1) \rightarrow (s_0(1 - p), s_1 + (s_0 - s_1)p) \end{eqnarray*} \]

那么显然当\(s_0 \leq s_1\)时,加入任何礼物都不会使得答案更优。
并且有:

\[\begin{eqnarray*} s_1 = s_0\sum\limits_{p \in T} \frac{p}{1 - p} \end{eqnarray*} \]

大力猜测从大到小选。。。

D - Play Games with Rounddog

题意:
给出一个字符串\(S\),每次询问给出\(l, r\)表示\(T = S[l, \cdots, r]\)
现在\(Calabash\)要从\(S\)中选择若干个子串\(s_i\),使得\(T\)是他们的后缀,令\(cnt_i\)为子串\(s_i\)\(S\)中的出现次数。
要保证\(w_{cnt_i}\)是线性无关的,在此基础上要保证\(\sum w_{cnt_i}\)尽量大。

思路:
保证\(w_{cnt_i}\)是线性无关的,那么就是他们可以形成一个线性基。
考虑线性基是个拟阵,具有贪心选择性质。
再考虑选择的子串中都有\(T\)为他们的后缀,也就是说选择的结点是\(SAM\)\(parent\)树上表示\(T\)的结点的子树中的结点。
也就是说选择范围是一棵子树。
那么我们对于每个点维护一个其子树构成的线性基,考虑线性基的大小为\(logW\),那么我们将每个点按\(w_{cnt_i}\)从大到小排序,每次暴力更新祖先的线性基,往上爬的过程中,如果某一步不能更新了,那么就\(break\)掉。
因为每个点的线性基大小很小,大概\(64\),所以均摊下来更新的次数大概是\(O(nlogW)\),每一次更新的复杂度为\(logW\),所以总的时间复杂度为\(nlog^2W\)
再考虑查询。
只要找到能表示出\(S[l, r]\)的深度最小的结点,那么它线性基里面的元素和就是答案。
深度最大的显然是表示出\(S[1, r]\)的结点,这个可以预处理,然后倍增往上爬即可,只要当前结点的长度大于等于\(r - l +1\),那么该节点就可以表示\(S[l, r]\)
因为祖先结点表示的字符串是当前结点的后缀。

E - Welcome Party

题意:
\(n\)个人,每个人的唱歌的能力值为\(x_i\),跳舞的能力值为\(y_i\)
现在选择一些人唱歌,一些人跳舞,使得唱歌的能力值的最大值与跳舞的能力值的最大值的差值最小。

思路:
排序一维,然后枚举这一维的最大值。
然后枚举的这个一定要选这一维,这一维小于这个数的可以选这一维也可以选另一维。
这一维大于这个数的一定不选这一维。
那么就用堆维护一下可选可不选的那些人,决定让他们选哪儿。

G - Closest Pair of Segments

题意:
\(n\)条线段,找两条相距最近的线段。

思路:
将线段按左端点排序,然后\(n^2\)枚举,但是注意对于一个\(i\),枚举到一个\(j\)的时候,\(j\)的左端点与\(i\)的右端点的\(x\)的差值已经大于\(ans\)了。
那么就不用再往下枚举了

H - Coins

题意:
\(n\)对硬币,每一对有\((a_i, b_i)\),现在对于每一对硬币,有三种选法:

  • \(a_i, b_i\)都不选.
  • 只选\(a_i\)
  • \(a_i, b_i\)都选

\(f(k)\)表示选择\(k\)个硬币的最大值。
\(f(1) \cdots f(2n)\)

思路:
考虑从\(f(i) \rightarrow f(i + 1)\),只有四种选择:

  • 从没有选过的硬币对中选择一个\(a_i\)
  • 从已经选过的硬币对中选择一个\(b_i\)
  • 退掉一个\(a_i\),选择一对\((a_j, b_j)\)
  • 退掉一个\(b_i\),选择一对\((a_j, b_j)\)

用堆维护即可。

I - Block Breaker

签到。

K - Make Rounddog Happy

题意:
有一个序列\(a_i\),选在要求找出有多少个子段是好的。
一个子段\([l, r]\)是好的:

  • 这个子段中的所有数都互不相同
  • \(max(a_l, \cdots, a_r) - (r - l + 1) \leq k\)

思路:
处理出每个数的管辖范围。
然后统计这个范围内有多少个过这个数的区间是好的。
因为是枚举每个数作为最大值,那么我们枚举短的那一段。
然后可以预处理出\(f_i, g_i\)分别表示这个数上次出现的位置,下次出现的位置。
那么一段区间\([l, r]\)中的每个数都不同,当且仅当\(max(f_l, \cdots f_r) < l\),或者\(min(g_l, \cdots, g_r) > r\)
那么可以直接二分找到合法左界,并且可以通过第二个条件直接算出合法左界范围。
然后枚举每个右端点或者左端点,计算出另一个端点范围即可。

posted @ 2019-08-28 20:49  Dup4  阅读(204)  评论(0编辑  收藏  举报