• 寒武纪camp Day4


    补题进度:7/11

    A(博弈论)

    B

    待填坑

    C(贪心)

    题意:

      一个序列是good的当且仅当相邻两个数字不相同。给出一个长度为n的数列,每个数字是ai。定义一种操作就是把a中某个元素拿到首位去,问最少需要多少次操作才能让数列a变成good的。如果不可行则输出-1。

      n<=1000,1<=ai<=n

    分析:

      我们先来判-1的情况,当且仅当出现次数最多的那个数字的出现次数超过了$frac{n}{2}$

      然后我们再来考虑一般的情况,我们把那些需要移动的数字全部拿出来记录一下,即b[i]表示至少要把b[i]个数字i提到前面去

      假设目前一共要移动m个数字,那么如果出现次数最多的数字的出现次数不超过$frac{m}{2}$,那么是很美好的,因为这样我们一定可以用m此操作让它们跑到前面去并且不冲突

      但是如果出现最多的次数超过了$frac{m}{2}$,那么我们就需要用额外的本不需要动的数字来填充其中了,讨论一下即可

      注意还要讨论一下第一位数字的值

    D(后缀树)

    题意:

      给出一个字符串S,一个整数l,一个整数k

      |S|<=2e5,l<=2e5,0<=k<=1e12

      我们需要求出一共有多少个长度不超过l的字符串T满足条件,答案可能很大,对1e9+7取模

      要满足的条件是以下程序段跑出的tot的值>=k

      

    分析:

      考虑一个简单的问题,给定了一个字符串T,我们要如何快速统计出tot的值

      tot的计算过程实际上是把S的每个后缀当作一个字符串,然后让T和每个字符串去求一个LCP,然后把所有LCP相加

      很自然的想到把S的每个后缀全部加到一个Trie树中

      那么我们定义一个点的value是它在Trie树的子树中单词节点的个数,那么我们只需要让T在Trie树上走,把经过点的value都加起来就是答案了,进一步的我们可以对于每个点,求出这个点到root这条链上的所有value的和,那么答案就是分叉点处的Σvalue

      这明显可以用后缀树优化,所以复杂度是O(n)的

      好现在我们再来考虑如何统计数目,统计数目也是很简单的,我们只需要枚举分叉点的位置,然后后面的那些位任意取(当然第一个自由元并不是26种),累加即可

      我们为了优化复杂度,把这个计算过程搬到后缀树上即可,中间的计算需要在纸上算算,本质上是算等比数列求和

      建后缀树的话,只需要建出逆序的SAM,然后按照slink建树就行了

      时间复杂度O(n)

    E(dp)

    题意:

      给出n,m,p

      给出n个m维向量,向量的每一位都是0/1

      问有多少个集合S,其中异或运算在S中是封闭的,且T∈S

      答案对p取模

      1<=n<=100,1<=m<=min(2000,2^n),1<=p<=1e9

    分析:

      S实际上就是包含T的线性子空间,所以就是求秩为m-rank(T)的线性子空间的个数

      我们考虑生成线性子空间的线性基的过程,从高位到低位放线性基

      每次我们有两种决策,那就是在当前列的主元位置放一个1(上面行的对应列都必须是0),或者当前位置放置0,之前有元素的行的对应位置可以随便填0/1

      于是我们就有了dp式子,dp[i][j]=dp[i-1][j-1]+dp[i-1][j]*2^j

      dp[i][j]表示填了i列填了j个主元的方案数

    F(记忆化搜索+论文剪枝)

    待填坑

    G(贪心)

    题意:

      给出一个1~n的排列,你可以把它分割成最多k段并且可以把这k个段进行排序,输出你能得到的最小字典序。

      n<=1e5

    分析:

      贪心着来,先把1砍出来,然后把2砍出来……

      这样可能会面临剩下最后一刀,但是不能把下一个数字砍出来了(因为可能需要两刀),去讨论最后一刀的情况就行了

    H(标记回收线段树)

    题意:

      给出一个长度为n的数组a[],有q个操作,操作有两种

        1 l r v :把a[l..r]全部改成数字v

        2        :撤销目前存在的最早的1操作

      对于每次操作之后,你需要计算数组的数字和,并把它累加起来最后输出

      n,q,v<=1e5

    分析:

      有了2操作,很容易想到是可持久化线段树,但是仔细一想,区间覆盖操作是不支持减法的,所以可持久化线段树好像无法做

      我们可以考虑这样来做,第i次1操作就把对应区间的值改成i,然后删除一个操作i就是把数组里所有数字i删除,变成初始状态

      因为是按照操作顺序删除操作的,所以这样是正确的

      我们只需要考虑用线段树来维护这个过程就行了

      我们假设刚开始每个位置染的颜色是inf(表示没有被染,是原来的值)

      我们现在线段树要处理问题的核心是“将数组中所有颜色i全部删除,变成inf,维护区间和”

      我们可以维护一下区间颜色min,如果一个区间颜色min>i,那么就不需要进去改颜色了(因为改颜色的过程是递增的)

      这样每次删除的话时间复杂度是O(颜色段数),这样可行吗?

      我们可以来分析一下,刚开始加入一个颜色区间,该颜色区间有log段,然后以后在染色的过程中,最多把之前的一个颜色分成两部分,所以一次修改操作只会让总段数多出log段,整体时间复杂度还是在O(nlogn)量级的

      有一点需要注意,在删除一个区间的标记之后,我们还需要将它子树里的标记全部清空(或者在做修改操作时候清空子树标记也是可行的),所以我们的线段树还需要标记回收,这也是不影响复杂度的

    I

    待填坑

    J

    待填坑

    K(不平等博弈)

    题意:

      在一个n个点的树上,Alice和Bob要进行博弈,首先Alice在任意一个地方下一个白棋,然后Bob在一个白棋的周围下个黑棋,然后Alice在一个白棋的周围下一个白棋……谁不能操作就算输

      n<=100

    分析:

      这是个不平等博弈,所以考虑用dp解决

      dp[i]表示在以i为根的子树上下棋,Alice先手在根下,最终Alice会比Bob多走多少步

      那么在i的k个分叉中,Bob会先选择一个dp[u]最大的一个下黑棋,不让Alice下白棋,然后Alice会选择dp[u]第二大的点下白棋,然后Bob会选择一个dp[u]第三大的点下黑棋……

      那么把dp[u]排序后,我们去累加一下求和就能得到dp[i]的值了

      注意一点,最后dp[i]=max(dp[i],0),即如果走这个子树Alice比Bob走的少,那么Alice不会选择走这个子树

      最后看一下dp[1]的值和0的大小关系就知道是Alice赢还是Bob赢了

      时间复杂度是O(nlogn)的

  • 相关阅读:
    洛谷—— P3353 在你窗外闪耀的星星
    洛谷—— P1238 走迷宫
    洛谷—— P1262 间谍网络
    9.8——模拟赛
    洛谷—— P1189 SEARCH
    算法
    May 22nd 2017 Week 21st Monday
    May 21st 2017 Week 21st Sunday
    May 20th 2017 Week 20th Saturday
    May 19th 2017 Week 20th Friday
  • 原文地址:https://www.cnblogs.com/wmrv587/p/8486301.html
Copyright © 2020-2023  润新知