• Codeforces Round #670 题意及思路


    A题

    题意

    题目给出 $ t $ 组数据,对于每组数据:
    给出一个数列,你需要将这个数列划分成两个集合 $ A $ 和 $ B $ ,并最大化 $ mex(A)+mex(B) $ 。
    $ mex $ 的定义:$ mex(A) $ 为最小的没有在集合 $ A $ 中出现过的非负整数的值。

    思路

    如果整个数列没有 $ 0 $ ,那么答案肯定是 $ 0 $ 。
    如果有 $ 1 $ 个 $ 0 $ ,那么其中一个集合的 $ mex $ 值肯定是 $ 0 $ 了,不妨另该集合 $ A=∅ $ ,使所有数都在另一个集合 $ B $ 中,答案即为 $ mex(B) $ 。
    如果有 $ 2 $ 个 $ 0 $ ,那么 $ 2 $ 个 $ 0 $ 一定要分成 $ 2 $ 组放,那么再用同样的方法研究 $ 1 $ 。
    总结以上步骤,先统计每个数出现的次数, $ mex $ 较小的集合的 $ mex $ 值应该是从 $ 0 $ 开始第一个不足 $ 2 $ 个的数 $ x $ ,$ mex $ 较大的集合的 $ mex $ 值应该是从 $ 0 $ 开始第一个没有的数 $ y $ 。答案即为 $ x+y $ 。

    B题

    题意

    题目给出 $ t $ 组数据,对于每组数据:
    给定 $ n $ 个数,找出 $ 5 $ 个数,让它们的乘积最大。每个数可正可负。

    思路

    如果只有 $ 5 $ 个数,输出这 $ 5 $ 个数的乘积。
    如果最终得到的乘积一定是负数(即所有的数都是负数),则选择最大的 $ 5 $ 个负数。
    如果最终得到的乘积一定是 $ 0 $ (即不足 $ 5 $ 个非零数),则答案为 $ 0 $ 。
    否则分类, $ 5 $ 个数中选择 $ 0,2,4 $ 个负数。

    C题

    题意

    题目给出 $ t $ 组数据,对于每组数据:
    给出一棵树,你需要通过,先任意删除一条边,再任意增加一条边,使得树的重心个数只有一个,且仍满足为树的形式。

    思路

    有一个结论,就是树的重心只有可能是 $ 1 $ 个或 $ 2 $ 个,且如果有 $ 2 $ 个,这两点一定相邻。
    如果有 $ 1 $ 个重心,随意删去一条边,再把他加回来。
    如果有 $ 2 $ 个重心,设两个重心为 $ c_1,c_2 $ ,可以删去 $ c_2 $ 和非 $ c_1 $ 的点 $ v $ 的边,然后把 $ v $ 和 $ c_1 $ 连起来。易证明这是正确的。

    D题

    题意

    给定一个序列 $ a_1,a_2,...a_n $ ,长度为 $ n $ 的序列 $ b,c $ ,满足 $ a_i=b_i+c_i $ ,且 $ b $ 为不下降序列, $ c $ 为不上升序列。
    有 $ q $ 个操作,每次操作可以把 $ [l,r] $ 的数增加 $ x $ 。求每次操作后最小的 $ max(b_i,c_i) $ 。

    思路

    先考虑原始序列,设 $ k $ 为正数,若 $ a_{i+1}=a_i+k $ ,那么 $ b_{i+1}=b_i+k,c_{i+1}=c_i $ ;若 $ a_{i+1}=a_i-k $ ,那么 $ b_{i+1}=b_i,c_{i+1}=c_i-k $ 。$ max(b_i,c_i) $ 一定是 $ b_n,c_1 $ 中的一个。为了使答案最小,应该使 $ b_n,c_1 $ 尽量接近,即相差 $ 0 $ 或 $ 1 $ 。那么我们可以假设 $ a_0=0,b_0=0 $ ,然后根据上述规则分别求出 $ b_n,c_1 $ ,最后的答案为 $ ceil(b_n+c_1)/2 $ 。
    然后再考虑如何更新答案,如果暴力更新时间复杂度是 $ O(nq) $ 。思考求出 $ b_n,c_1 $ 的过程。设 $ {d_n} $ 为 $ {a_n} $ 的差分数列,则 $ b_n $ 是 $ {d_n} $ 正项之和, $ c_1 $ 不是 $ d_1 $ 就是 $ 0 $ 。而区间加可单点修改 $ {d_n} $ ,时间复杂度变为 $ O(n+q) $ 。

    E题

    题意

    交互题。
    已知 $ n $ , 有一个未知数 $ x (1≤x≤n) $ ,你需要求出 $ x $ 的值。
    一开始,你有一个集合 $ S $ 由从 $ 1 $ 到 $ n $ ,你可以对这个集合执行不超过 $ 10000 $ 次 $ A,B,C $ 操作(总和不超过)。
    $ A: A a $ ,表示求出 $ S $ 中 $ a $ 的倍数的个数 $ (1≤a≤n) $ .
    $ B: B a $ ,表示求出 $ S $ 中 $ a $ 的倍数的个数并将这些 $ a $ 的倍数从 $ S $ 中删去( $ x $ 是不会被删掉) $ (2≤a≤n) $ 。
    $ C: C a $ ,表示你知道了 $ x=a (1≤a≤n) $ 。
    $ a $ 为整数。

    思路

    很容易想到一个暴力做法:对于每一个小于 $ n $ 的质数 $ p_i^1 $ ,删除 $ p_i^1 $ 的倍数后询问 $ p_i^1 $ 的倍数剩余多少个,如果有剩余说明 $ p_i $ 是 $ x $ 的质因子,再依次删除并询问 $ p_i2,p_i3...p_i^k $ 是否有剩余,找出 $ p_i $ 的个数,并计入答案。但是 $ 1e5 $ 以内的质数有 $ 9562 $ 个,每一个都这样操作会超过限制,需要优化。
    容易想到的是: $ x $ 里至多含有 $ 1 $ 个大于 $ sqrt(n) $ 的质因子。故对于不大于 $ sqrt(n) $ 的数,我们可以采用暴力做法,即最多只有 $ 66 $ 个质数采用暴力做法,可以接受。此时分两种情况。

    1. $ x $ 有不大于 $ sqrt(n) $ 的质因子,那么就依次删除并查询当前答案与大于 $ sqrt(n) $ 的质数的乘积是否有剩余,如果有剩余那么就是这个数,如果全部无剩余那就是当前答案。
    2. $ x $ 无不大于 $ sqrt(n) $ 的质因子,那么答案只有可能是大于 $ sqrt(n) $ 的某一质数或者 $ 1 $ 。大于 $ sqrt(n) $ 的质数仍有很多,不能暴力处理。可以用分块的思想,先统计一次剩余数的个数,然后删除 $ 50 $ 个数,再次统计剩余数的个数,如果正好少 $ 50 $ 个则可以继续向后查询,如果只少了 $ 49 $ 个那说明 $ x $ 在这 $ 50 $ 个数之中。如果也没有大于 $ sqrt(n) $ 的质数,那么答案就是 $ 1 $ 了。

    特殊的,感觉 $ n=1 $ 的时候要特判。

    提交记录

    写的很乱,请多多包容!!!
    $ A $ 题: A
    $ B $ 题: B
    $ C $ 题: C
    $ D $ 题: D
    $ E $ 题: E

  • 相关阅读:
    记一次给自己的本子更换一个SSD盘
    喜欢的电影
    一个人没有出息的9大根源
    经典思维模式
    Linux基础入门教程
    XML
    UML
    Linux最常用的基础命令
    IP地址
    http协议
  • 原文地址:https://www.cnblogs.com/Mercury04/p/13701205.html
Copyright © 2020-2023  润新知