牛客练习赛10

地址:https://www.nowcoder.com/acm/contest/58#question

A(贪心)

B(贪心+栈)

C(manacher+后缀数组)

分析:

  考虑枚举字符串的对称轴在哪

  容易发现我们希望从对称轴开始尽可能向两边扩展成为回文串,在不能再扩展的位置就是我们的分割线,然后我们求分割线位置对应两个串的lcp即可(后缀数组实现)

  所以可以先manacher跑出p[i]表示以i为中心向两边扩展的最大长度,然后将S1倒序接在S2后面做后缀数组求lcp即可

  注意回文串的中心可以在S1也可以在S2中,所以要做两次

  事实上,可以直接用后缀数组得到p[i],不需要额外跑manacher

  时间复杂度O(nlogn)

D(模拟)

E(莫队算法+分块)

分析:

  以为要莫队算法+平衡树,但实际上可以用分块来代替平衡树

  我们把所有可能的出现次数(即1~n)分块,每一块标记出里面"出现次数"的个数,于是每次询问就可以在O(sqrt(n))时间内找到k1对应的“出现次数”

  对于每个出现次数,对里面的数字进行分块,也是同样处理,找到k2对应的数字

  时间复杂度O(nsqrt(n)+msqrt(n))

F(莫队算法+分块+快速幂分块套路)

分析:

  对于一个询问我们可以计算每个数字的贡献,假设数字x出现了y次,那么我们发现就是个等比数列求和,求和后结果就是$x*(2^{r-l+1}-2^{r-l+1-y})$

  第一反应就是直接莫队算法维护就行了,但这题每个询问之间模数不同,所以不能直接维护ans

  把那个贡献拆成两部分$x2^{r-l+1}$,$x2^{r-l+1-y}$

  对于第一部分很好维护,我们只需要维护目前所有出现过的数字的和就行了

  对于第二部分,我们很自然的想到按照y对他们分类计算,我们不要记录答案,我们去记录2的指数

  因为y出现的个数一定是sqrt(n)级别的,所以这是ok的,只需要每次维护的时候用链表来维护出现过的次数就行了

  这样的话维护是O(nsqrt(n))的,询问是O(msqrt(n)logA)的,其中logA是快速幂的复杂度

  然而恰恰就是快速幂这里超时,这里要用题解的一个套路来把log去掉

  比如现在在区间[1,n]里挑比较多的数字x,你需要求每个2^x % p的结果,一般的做法就是每个询问都去跑log的快速幂

  但我们可以对x的值域进行分块[1..sqrt(n)] [sqrt(n)+1..2*sqrt(n)] [2*sqrt(n)+1,3*sqrt(n)] ....... 一共sqrt(n)块

  我们预处理出x=1,2,3,...,sqrt(n)时,2^x %p 的值

  我们预处理出x=sqrt(n),2*sqrt(n),3*sqrt(n)...,sqrt(n)*sqrt(n)时,2^x%p的值

  现在我们要求2^x的值,只需要找到x所在的这个块,然后将x所在块前面的整段的值乘上x在当前块中的排名的对应值就行了,这是O(1)的

  于是这道题时间复杂度就是O(nsqrt(n)+msqrt(n))的了,就能过了

posted @ 2018-01-13 17:09  Chellyutaha  阅读(224)  评论(0编辑  收藏  举报