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\)的礼物会使得:
那么显然当\(s_0 \leq s_1\)时,加入任何礼物都不会使得答案更优。
并且有:
大力猜测从大到小选。。。
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\)。
那么可以直接二分找到合法左界,并且可以通过第二个条件直接算出合法左界范围。
然后枚举每个右端点或者左端点,计算出另一个端点范围即可。