zoukankan      html  css  js  c++  java
  • 牛客练习赛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))的了,就能过了

  • 相关阅读:
    spring-session+Redis实现Session共享
    SQLServer语法常用总结
    [PDFBox]后台操作pdf的工具类
    类加载器
    SQLServer常用分页方式
    Tesseract识别图片提取文字&字库训练
    AbstractQueuedSynchronizer的简单介绍
    CountDownLatch 闭锁、FutureTask、Semaphore信号量、Barrier栅栏
    Java线程实现的第三种方式Callable方式与结合Future获取返回值
    原子类型的使用&Unsafe&CAS
  • 原文地址:https://www.cnblogs.com/wmrv587/p/8279940.html
Copyright © 2011-2022 走看看