UOJ Logo hehezhou的博客

博客

UOJ NOI Round #6 Day1 题解

2022-08-06 17:57:28 By hehezhou

面基之路

idea from he_____he, data,solution from hehezhou

算法一

首先需要注意到最重要的结论:题意等价于所有人走到同一位置所需最短时间。证明只需要让所有网友在面基成功之后跟随 hehe 蚤行动即可。

对于子任务 1,不难发现最终汇合点一定在某个点上或某条边正中。如果汇合点在边的非中点位置,移动到端点或中点,一定有一种更优。

只需要求出会合到每一个位置的答案即可。时间复杂度 O(k(nlogn+m)),期望得分 30

算法二

对于子任务 2,不难发现 T 就是最远点距离除以二。

首先会合时间不可能更早,因为 1 和最远点的距离达到了 2T。而只需要让所有人移动到 1 和最远点的带权中心就是一组合法方案。

算法三

首先汇合点在点上的情况是简单的,考虑汇合点在边上的情况。

定义边的左右侧是它的两个端点,枚举每个人是从哪一侧进入这条边的,每侧只需要考虑最晚进入的人即可,答案不难计算。

时间复杂度 O(m2k+knlogn),期望得分 85

算法四

由于每侧只需考虑最晚进入的人,对于每条边,一定存在一种最优方案,将所有人按照到达左侧时间排序后,一个前缀从左侧进入而剩余的后缀从右侧进入。

时间复杂度 O(knlogn+mklogk),期望得分 100

bonus

如果 hehe 蚤的速度是 a 而网友们的速度是 b,这个问题又该怎么解决呢?

这个问题会在数日后被加入 uoj 题库。

机器人表演

idea, data from djq_cpp, solution from hehezhou

本题改编自 CPIdeas (https://codeforces.com/blog/entry/104374) 生成的题面:

You are given a string S consisting of 0 and 1. You can do the following operation on S any number of times: Choose a non empty substring T of S, and append 0 to the beginning and 1 to the end of T. The resulting string will be S again. How many different strings will S be after the operations? Find the count
modulo 998244353.

算法一

我会状压!

接下来令左括号对应 0,右括号对应 1,合法括号前缀是满足任意前缀 0 不少于 1 的串,合法括号串是 01 个数相等的合法括号前缀,AB 可以合并出 C 等价于 C 可以被划分为两个子序列分别等于 AB

首先我们考虑给定一个串 T,判断其是否可以通过合并串 S 和某个括号串得到。这可以在 O(|S||T|) 的时间内完成,具体的,设 fi,j(ij) 表示是否存在一个合法括号前缀使得它和 S[1:j] 可以合并出 T[1:i]。考虑转移,有以下两种转移:

  1. fi,jfi+1,j+1(Si+1=Tj+1)

  2. fi,jfi+1,j(ai+1bj)

其中若 Ti 是左括号,ai=ai1+1,否则 ai=ai11b 是定义在 S 上的类似序列。第一种转移显然正确,第二种转移是因为:所有合并方案中,合法括号前缀的两种数量都是固定的。

如果 f|T|,|S|=truea|T|=b|S|,则串 T 可以通过合并串 S 和某个括号串得到。

对应这个 dp,我们可以列出求解原题的状压 dp。dpi,j,V 表示已经填好了 T 的前 i 位,fi,k 等于 V 的第 k 位,ai=j,转移按照上述转移式对应转移即可。

时间复杂度 O(2nn(n+t)2),可以通过子任务 1,2,4,期望得分 45

如果省略无用状态,可以额外通过子任务 3,期望得分 60

算法二

我是打表大师!我打表转移找到规律了!

规律就是:对于固定的 S,i,j,非零 dpi,j,V 两个后继状态的 V 的最高位只和当前 V 的最高位有关。

可以只记录 V 的最高位,状态数减少为 O(n(n+t)2)

时间复杂度 O(n2(n+t)2),进一步得到转移规律可以做到 O(n(n+t)2),期望得分 75100

算法三

我喜欢严谨做题!我要证明这个结论!

先注意到几个重要性质:

  1. 两个合法括号前缀合成的串一定是合法括号前缀。考虑定义不难得出。

  2. fi,j=1,则有 aibj。考虑转移或考虑 dp 意义均不难得出。

考虑当前已经匹配了前 i 位,ai 确定,并且可以匹配的 S 的最长前缀是 k,考虑在算上第 i+1x 以后,可以匹配的 S 最长前缀:

  1. Sk+1=x:显然新的最长前缀是 k+1

  2. 否则若 x=0(即左括号) 或 ai>bk:那么 ai+1bk,新的最长前缀是 k

  3. 否则有 x=1(即右括号)且 ai=bk,这种情况较为复杂。先给出结论:新的最长前缀 k=maxt<k,bt<bkt。第一步证明这个前缀是合法的:不难发现 S[k+1,k] 是一个合法括号前缀,否则就存在更大的位置满足 bt<bk。首先证明 fi,k=true,只需要将 fi,k 对应的合法方案中,S[k+1,k] 对应的子序列划为合法括号前缀部分,由性质 1 我们就得到了 fi,k 对应的一组方案,因此 fi,k=true 且可以转移到 fi+1,k。然后我们证明不存在更长的前缀 x 可以匹配 T 的前 i+1 个位置,否则 bxbk>ai1=ai+1,与性质 2 矛盾。

至此我们证明了这个结论。

期望得分 100 分。

稳健型选手

idea,data,solution from xyr2005

谢罪!谢罪!谢罪!谢罪!谢罪!

算法一

我会暴力!状压当前剩下哪些数,复杂度 O(n2n+q),可以通过子任务一获得 10 分。

算法二

我会观察性质!先考虑单组询问。

首先,如果 n 是奇数,那 QAQ 蚤会在最后一次取最后一个数,转化成前 n1 个数的问题,容易发现这是最优的。所以我们可以假设 2n

考虑 QAQ 蚤取的数的集合要满足什么条件。令序列 bi=0/1 表示这个位置最终 QAQ 蚤 取不取。

那 QAQ 蚤可以贪心每次取 bi=1 的最靠前的那个,那么可以发现 一个 b 合法当且仅当 bi=n2i[1,n],j=1ibji2

我们可以 dpi,j 表示考虑了前 i 个元素,总共取了 j 个,和最大是多少,转移时保证 ji2 即可。

复杂度 O(n2q) ,可以通过子任务一二获得 20 分。

算法三

考虑优化算法二。

可以使用反悔贪心,从前往后扫,维护 QAQ 蚤取了哪些数。

每次加进来两个数 x,y,首先假设 x,y 都取了,这时候取了的数的总数是 i2+1,再删掉一个最小的已经取了的数。

用堆维护上述过程,复杂度 O(nqlogn) ,可以通过子任务一二三获得 40 分。

算法四

我们发现,前 2i 个取了 i2i 个取了 i 个。

于是算法三也可以倒着来做,从后往前扫,维护 QAQ 蚤没取哪些数。

每次加进来两个数 x,y,首先假设 x,y 都没取,这时候取了的数的总数是 i21,再取一个最大的没取的数。

于是我们现在可以在 O(logn) 复杂度内,向前加两个数,向后加两个数,使用不删除莫队维护。

复杂度 O(nqlogn),可以通过子任务一二三四获得 70 分。

使用压位trie/veb 维护,复杂度 O(nqlogwn)/O(nqloglogn),期望得分 70 分,实际得分 100 分。

算法五

继续优化算法四。

使用分治,用主席树对 [l,mid] 的每个后缀维护取了哪些数,对 [mid+1,r] 的每个前缀维护没取哪些数。

然后考虑合并 [x,mid][mid+1,y],那会发生的变化是,[x,mid] 中一些取了的数现在不取了,[mid+1,y] 中一些没取的数现在取了。假设 [x,mid] 中发生变化的数的集合是 S[mid+1,y] 中发生变化的数的集合是 T,那么 |S|=|T|maxS<minTS 是一段前缀,T 是一段后缀。于是我们二分 k ,找到最大的 k 满足左边第 k< 右边第 k 大,然后就知道了 S,T,于是做完了。

复杂度 O((n+q)log2n),可以通过子任务一二三四五获得 100 分。

评论

其实 T3 的算法二卡卡常就能在 2.7s 左右过子任务 3,得到 40 分。 我的提交记录:https://uoj.ac/submission/570320(20 分是因为前两个子任务 WA 了,只过了子任务 3)。
评论回复
Minion:不加循环展开的话有点卡(2.99s 左右),所以我加了循环展开。
Minion:我找到那个 20 分代码的问题了:在一个地方,我把 f[1] 写成了 f[0]……
这个是我过了前 3 个子任务的 O(n^2q) 代码:https://uoj.ac/submission/570953
提问:T2 题解什么时候发!
提问:T2 题解什么时候发!
提问:T2 题解什么时候发!
提问:T2 题解什么时候发!
将 0 表示成 '(',将 1 表示成 ')',加 t 对 01 可以看成加 t 对括号。 设 fi,j,k 表示长度为 i,与初始 01 串匹配长度为 j,新加的括号中左括号个数-右括号个数为 k 的方案数,然后按照每个括号分别是原来的括号、新加的括号来转移。 但还有一种情况:当 k 为 0 时,加入一个右括号不一定是不合法的,因为我们可以缩减匹配长度使得它合法。 直接做是 O(n3) 的。
评论回复
Sol1:错的吧,,,
hehezhou:我的评价是:歪打正着
chennengkuan:回复 @Sol1:然而这个确实是对的
mao1118:回复 @hehezhou:请问这个为啥是“歪打正着”?
hehezhou:回复 @mao1118:因为能匹配一个较长前缀不意味着能匹配一个较短前缀,反悔只在极少的特定位置是正确的,根据题解可以证明一个由于特定的关键位置,反悔转移正确,但是上述话语并没有提及这个关键性质。
提问:T2 题解什么时候发!
提问:T1 bonus 什么时候加!
提问:T1 bonus 什么时候加!
提问:T1 bonus 什么时候加!
提问:T1 bonus 什么时候加! 提问:T1 bonus 什么时候加! 提问:T1 bonus 什么时候加! 提问:T1 bonus 什么时候加! 提问:T1 bonus 什么时候加! 提问:T1 bonus 什么时候加!
提问:T1 bonus 什么时候加!
提问:T1 bonus 什么时候加!
评论回复
_map_:你怎么还没做
T1 bonus 加了,别骂了

发表评论

可以用@mike来提到mike这个用户,mike会被高亮显示。如果你真的想打“@”这个字符,请用“@@”。