zoukankan      html  css  js  c++  java
  • 模拟31 题解

    A. math

    考试时打的错解,
    取每个$a_i$与k的gcd,分别做背包由0直到k。
    但是复杂度有点问题,于是做了个筛。
    $O(k sqrt(k))$一定没有问题,在不构造特殊数据下很优秀。
    考后突然被自己一个简单的数据hack掉了。
    2 6
    2 3
    我的程序会输出
    5
    0 2 3 4 5
    然而显然1是可以被拼凑出来的。
    正解是求出k与所有的$a_i$的gcd。
    答案就是k/gcd,
    和首项为0,末项小于k的公差为gcd的等差数列。
    正确性是显然的。


    B. biology

    将所有的坐标放进结构体里,
    以a值排个序,
    直接$O(n^4)$暴力dp。

    把它优化成$O(n^2)$或者$O(n^2logn)$就可过。
    观察第三个部分分,得到一个性质:
    一行可以只由它的前一行转移过来。
    原因是b值不为负,而另一项为两点之间的距离。
    多走一次不会使答案变差。
    继续观察得到另一个性质:
    将两点距离中的横纵坐标拆开,
    即将$abs(x1-x2)+abs(y1-y2)$拆为类似$(x1+y1)-(x2+y2)$的四种形式。
    可以将不好维护的两点距离转化掉。
    只需知道每个点四个方向上的最大值即可。
    二维树状数组可维护,复杂度$O(n^2log^2n)$。

    为什么要关注确切的方向?
    按照事实考虑确实是需要的。
    在天使玩偶一题中,要求最小值。
    如果我们错误的选择了方向,可能会使本应取正的abs值取了负,使答案更小,也就错了。
    但本题中视答案更大为更优。
    如果做出一些可能会使答案更小的操作,是不影响最终答案的。
    于是直接把维护树状数组改成维护四个变量就可以了。
    这个题在考场上做的很坎坷,一点点把暴力的dp,拆成了恶心的数据结构,最终又化回了很简单的形式。



    C. english

    题中要求的区间比较难处理,
    显然枚举最大值在哪,找到它决策的左右区间。
    第一问一眼切了。
    异或显然按位处理,处理出每一位上1的个数的前缀和来区间查找。
    枚举最大值,只有0^1可得1,直接区间查找就完了。

    第二问还复杂一些,
    因为要统计方案数,显然维护trie树。
    要查询区间,可持久化啊,还不是很难打。
    仍然是枚举最大值,
    如果最大值左侧区间比较短,就枚举左侧区间上的数,查询右侧区间。
    反之则枚举右侧区间上的数,查询左侧区间。
    考场上实在是想不出来如何构造数据卡掉这个算法(实际上确实没有),就打了出来。

    复杂度的证明用了轻重儿子的思想。
    首先应当注意一些性质:
    求出的左右区间,必定满足
    $a[i]<a[l[i]-1]$
    $a[i]<a[r[i]+1]$
    任取i的决策区间中的j,
    $a[j]<a[i]$
    使初始区间为(1,n),不断找区间中的最大值,向左右递归,可以形成一棵二叉树。
    所以我们的算法就是不断枚举轻儿子查询重儿子。
    显然复杂度为$O(nlognlogmx)$。
    最坏情况是一棵完全二叉树。

    如果想到了正解的思想,
    也可以直接建树找轻重儿子,用启发式合并trie树做这一道题。
  • 相关阅读:
    团队项目冲刺第十天
    gradle文件配置
    idea无Android项目
    php第二次实验报告
    最长回文字串(hdu 3068)
    优先队列实现哈弗曼最小权值
    最小生成树 克鲁斯卡尔(Kruskal)算法求最小生成树
    背包问题------ 分类: ACM 2015-08-03 20:57 1人阅读 评论(0
    Cent Savings (DP) 分类: ACM dp 2015-08-0
    Judging Troubles (multiset查找) 分类: ACM STL
  • 原文地址:https://www.cnblogs.com/skyh/p/11406835.html
Copyright © 2011-2022 走看看