省选模拟71 题解

A. 王子

这个数据范围加上很奇怪的限制,其实就应该是网络流了。

可以首先钦定选择了 $A$ 类,然后将其中的一些替换为 $B$ 类。

其实与志愿者招募那个题挺像的,只不过原来是对于每个点选择 $[l,r]$ 个区间。

但是现在的问题是要求每个区间选择 $[l,r]$ 个数点。

其实并不难处理,将 $n-k+1$ 个区间视作 $n-k+2$ 个连成一条链的点之间的边即可。

这样每个点能造成的贡献其实就是一段连续区间,与志愿者招募一题很像了。

但是还有一个问题是,在本题中要求最大的收益,但是直接建图是存在正环的。

所以这个最大费用流就没得跑了。

考虑这样一个事情,一般的上下界网络流是钦定下界,然后去流上界-下界。

其实另一种做法是钦定上界,建反向边同样流上界-下界表示退流。

这样的话其实可以结合两种做法,只建负边权的边就可以解决这个问题。

 

B. 遇见

这个题的 $n^2$ 做法是显然的,然后发现 $n \leq 30000$ 而且时限还开了 $3s$。

那直接打个暴力,顺便卡卡常就结束了。

正解是考虑给每种数随机一个权值,然后区间 $[l,r]$ 成为答案仅当 $sum_r \oplus sum_{l-1} \oplus s_{l,r}=0$。

其中 $sum_i$ 表示前缀异或和,$s_{l,r}$ 表示 $[l,r]$ 区间内出现的数的异或和。

容易发现这是一个 $0/1\ trie$ 树问题,然后难点在于维护后者。

考虑每次移动右端点,更新可以更新的 $s_{l,r}$,这是一段连续的区间并且左端点是容易找到的。

所以分块维护这个 $0/1 \ tire$ 树,每次打个标记就好了。

 

C. 字符串

显然这个问题要用 AC 自动机解决,然后发现不会做。

看数据范围,有一个很奇妙的性质是点数 $\leq 50$。

加上循环这个玩意,就可以联想到这个东西一定是存在循环节的。

假设当前 $str$ 的长度为 $len$,那循环节的长度一定不超过 $50*len$。

所以暴力找循环节是可以接受的。

部分分提示了一些东西,比如可以用一个珂朵莉树来维护字符串 $S$。

点数 $\leq 50$是一个很好的东西,还有一个可以挖掘到的性质是 tire 树的深度是 $\leq 50$的。

因为 AC 自动机维护的是后缀,那也就是说对于每次我们只关注每个点的前 $50$ 个字符就足以得到当前状态。

考虑维护一个数组 $f$, $f_i$ 表示把 $S[1:i]$ 丢到自动机上匹配,得到的以 $r$ 为右端点的子串个数。

对于每次修改,只需要考虑循环节、循环节之前的部分、 $r$ 之后的不超过 $50$ 个字符。

对于循环节内的部分,用线段树区间覆盖即可维护。另外两者可以直接暴力。

对于每次询问,只需要将 $[l,r]$ 拆分为 $[l,l+50]$ 和 $[l+51,r]$。

前者长度很小,可以暴力维护。后者已经与左端点 $l$ 无关了,所以可以直接用 $f$ 数组,所以这题就做完了。

posted @ 2020-04-15 21:35  skyh  阅读(134)  评论(1编辑  收藏  举报