• UOJ pjudge LOJ 试题乱做 Part5


    最近模拟赛天天挂分, 不能再这样了啊, 警钟长鸣.


    \(\text{【LOJ\#2994】「JOISC 2015 Day1」复制粘贴 2}\)

    \(\color{green}{\text{[EASY]}}\)

    感觉还是有点难度的, 但是逆向思维确实是常见的套路.

    倒着一次考虑每个操作, 找到每个位置在操作前的位置, 找到第一个即可.

    时间复杂度 \(\mathcal{O}(kn)\) .


    \(\text{【LOJ\#2995】「JOISC 2015 Day1」愉快的标志设计}\)

    \(\color{green}{\text{[EASY]}}\)

    先断环为链, 我居然这都忘了, 想了好久.

    然后直接设 \(f_{i,j}\) 表示从 \(i\) 开始的 \(j-1\) 级串需要改最少要改多少个字符, 转移为 \(f_{i,j}=val(i,i+3\times 4^{j-1}-1)+f_{i+3\times 4^{j-1},j-1}\) .

    不难发现第二维没啥用, \(val\) 函数可以前缀和优化, 时间复杂度 \(\mathcal{O}(n\log{n})\) .


    \(\text{【LOJ\#2996】「JOISC 2015 Day1」有趣的家庭菜园 2}\)

    \(\color{green}{\text{[EASY]}}\)

    首先最后的答案一定是单峰状物, 考虑枚举峰, 然后两边独立, 先 \(dp\) 出两边的值, 最后合并.

    两边同理, 只考虑一边, 设 \(f_i\) 表示考虑到 \(i\) , 并且 \(i\) 必选的最大值, 朴素转移是 \(\mathcal{O}(n^2)\) 的, 考虑优化, 考虑 \(j\)\(i\) 的贡献, 不难发现可以线段树维护.

    时间复杂度 \(\mathcal{O}(n\log{n})\) .


    \(\text{【LOJ\#2997】「JOISC 2015 Day 1」卡片占卜}\)

    \(\color{green}{\text{[EASY]}}\)

    这题很 \(trivial\) 啊, 没想到该好好反思.

    首先差分还是可以想到的, 操作变成对两个点 \(+1\) , 然后我们可以把操作看成给两个点连边, 那么消去两个关键点就是这两个点的最短路.

    \(3\) 遍最短路即可, 时间复杂度 \(\mathcal{O}((n+m)\log{n})\) .


    \(\text{【LOJ\#2998】「JOISC 2015 Day2」Building 3}\)

    \(\color{green}{\text{[EASY]}}\)

    首先第一个条件很好理解, 在 \(B\) 中插入一个数, 但第二个条件就十分抽象了, 考虑转化, 不难想到, 作为最长不降子序列的 \(dp\) 数组, 需要满足的要求是, 对于每个 \(i\) 存在一个 \(j<i\) 满足 \(A_i=A_j+1\) , 有了判断合法的方式就好办了.

    先扫一遍求出对于每个位置有哪些限制, 如果限制多余两个答案就是 \(0\) , 从后往前扫计算填需要的数或者任意填即可, 注意容易算重, 要判断当前填的数和后面的数不一样即可.

    时间复杂度 \(\mathcal{O}(n)\) .


    \(\text{【LOJ\#2999】「JOISC 2015 Day2」Keys}\)

    \(\color{blue}{\text{[NORMAL]}}\)

    还是很有意思的一道题啊, 没想出来是我菜了.

    明显是按时间点排序, 考虑每个相邻的时间区间在什么条件下会有贡献, 以下 \(i\) 表示排序后第 \(i\) 个人.

    • \(i\)\(i+1\) 出, 无论什么情况都能贡献.
    • \(i\)\(i+1\) 进, 当且仅当 \(i+1\) 有钥匙才有贡献.
    • \(i\)\(i+1\) 出, 当且仅当 \(i\) 有钥匙才有贡献.
    • \(i\)\(i+1\) 进, 当且仅当两个人都有钥匙才有贡献.

    考虑计算贡献, 第一种直接计入答案, 第二三种把贡献记点上, 第四种把贡献记在边上, 原图变成若干条链, 将链链接一下, 变成序列问题, 直接 \(dp\) 即可, 设 \(f_{i,j,0/1}\) 表示前 \(i\) 个人给了 \(j\) 把钥匙, 第 \(i\) 个人是否有钥匙.

    时间复杂度 \(\mathcal{O}(n^2)\) .


    \(\text{【LOJ\#3000】「JOISC 2015 Day2」Road Development}\)

    \(\color{green}{\text{[EASY]}}\)

    离线, 先把树建出来, 同时可以处理出 \(-1\) , 对于剩下的操作, 如果是第一次加入的树边则不管, 否则树剖路径赋值, 对于询问, 直接是路径长度减路径和, 注意这个愚蠢的东西是森林不是一棵树.

    时间复杂度 \(\mathcal{O}(q\log^2{n})\) .


    \(\text{【LOJ\#3001】「JOISC 2015 Day 3」AAQQZ}\)

    \(\color{red}{\text{[HARD]}}\)

    难点在于我不会这个大分讨题还没有中文题解, 给个 \(\color{red}{\text{[HARD]}}\) 来纪念我读别人代码 \(1h\) 去理解做法.

    蒯张官方题解的图.

    zV8NdJ.png

    虚线部分是回文子串, 蓝色部分是排序部分.

    容易发现, 答案只可能是这几种形式.

    注意到第三种形式很好处理, 即计算出现次数最多的数字个数, 第一二和第五六种形式是对称的, 只处理一个方向, 翻转并反转之后再求一次即可.

    对于剩下的情况, 重新分为两类, 排序部分经过回文中心和不经过.

    可以预处理出 \(lcp_{l,r}\) 表示子串 \([l\cdots 1]\)\([r\cdots n]\)\(lcp\) , 对于前者枚举排序的最右位置, 并且根据另一边的子串应自己满足单调性不难求出答案.

    对于后者先枚举回文中心位置 \(i\) , 再根据排序外的另一边应具有单调性, 从 \(i-lcp_{i-1,i+1}-1\)\(i+lcp_{i-1,i+1}+1\) 两处开始匹配.

    时间复杂度 \(\mathcal{O}(n^2)\) .


    \(\text{【LOJ\#3002】「JOISC 2015 Day 3」Card Game Is Great Fun}\)

    \(\color{blue}{\text{[NORMAL]}}\)

    果然还是太菜了, 这种看起来就很直接的 \(dp\) 状态与转移都不会, 这里叙述两种做法, 一种 \(\mathcal{O}(n^3)\) , 一种 \(\mathcal{O}(\frac{n^3}{\omega})\) .

    注意到, 无论取哪张牌, 新的第三张牌都是原来的第四章牌, 所以考虑直接把这三张牌记录到状态里.

    \(f_{i,j,k}\) 表示第三张牌为 \(i\) , 第一张牌为 \(j\) , 第二章牌为 \(k\) , 上一次拿的牌为 \(i-1\) 的最大价值, \(g_{i,j,k}\) 表示第三章牌为 \(i\) , 第一章牌为 \(j\) , 第二章牌为 \(i-1\) , 上一次拿的牌为 \(k\) 的最大价值.

    刷表法转移, 考虑这次取走哪张牌, \(f\)\(g\) 相互转移, 时间复杂度 \(\mathcal{O}(n^3)\) .

    \(suf_i\)\(v_i\) 的后缀和.

    考虑上述 \(dp\) 的时候, 发现 \(f\) 的状态是形如 \(j,k,i,i+1,\cdots\) 的栈, \(g\) 是形如 \(j,i-1,i,i+1,\cdots\) 的栈, 如果我们知道某个状态可以到达, 那么实际上那个状态的答案就是 \(suf_1-\sum\limits_{i\in \text{Stack}}{v_i}\) , 所以实际上 \(f,g\) 可以开成 \(bool\) 型, 用 \(bitset\) 存储.

    考虑原 \(dp\) 的转移,

    \[\begin{cases}f_{i,j,k}\rightarrow f_{i+1,j,k}\\g_{i,j,k}\rightarrow f_{i+1,j,i-1}\\f_{i,j,k}\rightarrow g_{i+1,k,j}\\g_{i,j,k}\rightarrow g_{i+1,i-1,j}\end{cases} \]

    为了方便转移, 考虑交换 \(f\) 中的 \(j,k\) 两维, 并且对每张牌分别记录两个 \(bitset\) , \(rs,ls\) 分别表示此牌的后面能跟哪些牌, 前面可以是哪些牌, 继续考虑之前的转移以及限制.

    • \(f_{i,k,j} \rightarrow f_{i+1,k,j}\) , 条件是 \(i-1\) 后可以跟 \(i\) , 仅需判断 \(rs_{i-1,i}\) 是否为 \(1\) 即可.
    • \(g_{i,j,k}\rightarrow f_{i+1,i-1,j}\) , 条件是 \(k\) 后面可以跟 \(i\) , 仅需判断 \(g_{i,j,k} \land ls_i\) 是否为 \(1\) 即可, 进一步的 \(g_{i,j}\land ls_i\) 即可判断是否可以转移.
    • \(f_{i,k,j}\rightarrow g_{i+1,k,j}\) , 条件是 \(i-1\) 后面可以跟 \(j\) , 直接将 \(f_{i,k}\)\(rs_{i-1}\) 与起来即可.
    • \(g_{i,j,k}\rightarrow g_{i+1,i-1,j}\) , 条件是 \(k\) 后面可以跟 \(j\) , 跟情况二类似.

    最后考虑计算答案, 对于 \(g\) 的答案是好计算的, 因为与 \(k\) 无关, 答案即为 \(suf_1-suf_{i-1}-val_{j}\) . 考虑如何计算 \(f\) , 答案即为 \(suf_1-suf_i-val_j-val_k\) , 由于已经交换了 \(j,k\) , 考虑固定住 \(k\) , 对于某一个 \(j\) , \(i\) 肯定是越大越好, 我们可以从大到小枚举 \(j\) , 每次维护新出现的 \(j\) , 并更新答案.

    时间复杂度 \(\mathcal{O}(\frac{n^3}{\omega})\) .


    \(\text{【LOJ\#3004】「JOISC 2015 Day 4」Inheritance}\)

    \(\color{green}{\text{[EASY]}}\)

    考虑仿照 \(Kruskal\) 算法, 将边按边权从大到小排序, 开 \(k\) 个并查集维护第 \(k\) 个人的情况, 至于一条边应该加入哪个并查集, 二分即可.

    时间复杂度 \(\mathcal{O}(m\log{m}+m\log{k})\) .


    感觉 \(2015\) 的题大部分简单了啊.

  • 相关阅读:
    ny2 括号配对问题
    ny14 会场安排问题
    杭电ACM题目分类
    hdoj2037 今年暑假不AC
    ny37 回文字符串
    算法 字符串的排列组合
    手撸IoC
    Java设计模式
    多种方法求java求整数的位数
    二叉树之 二叉树深度
  • 原文地址:https://www.cnblogs.com/Lonely923/p/16901045.html
Copyright © 2020-2023  润新知