打了两次div2,终于能打div1了,还是挺兴奋的
Positive AND(10.2)
Replace for X(10.3)
Inversions(10.4)
D-Dimensional MST(10.4)
Adding Squares(10.4)
Compress all Subsegments(10.5)
Rooted Minimum Spanning Tree(10.5)
Random Knapsack(10.8)
Village Road Network(未做)
Rooted Minimum Spanning Tree
回顾Kruskal算法,令(G_k)为根据kruskal算法生成的有(k)条边的森林
引理1:任意(k)边森林(T)的最大边大于等于(G_k)的最大边
证明:
反证法:假设最大边小于(G_k)的最大边
令(e)为最小属于(T)不属于(G_k)的边,显然其小于(G_k)
根据kruskal算法流程,(e)加入(G_k)后形成了环,且环中的边比其小,令(f)为在环中某条不在(T)的边(容易证明一定存在)
将(T)更改为(T-e+f),最大边未增加,通过反复操作,可知假设非真
引理2:任意(k)边森林(T)总重大于等于(G_k)总重
证明:
根据引理1,可删除(T)、(G_k)最大边
通过归纳得证
考虑除(1)以外的集合,初始时有(n-1)棵树,每次合并两个连通块,将两个连通块的两条与(1)相连的边割掉一条,(1)的度数(-1)
一条边对答案的增量为:重量-两端到(1)的最大值。过程同Kruskal
考虑正确性:证明引理1依然成立,在(T)与(G_k)的边权看作插进来对答案的增量,由于当一条边插入(G)时其他边的增量会增大,这意味着该边增量一直会比其他边小,容易证明引理1的正确性
但我们需要考虑的是,合并两个连通块后,与这个连通块相邻的边的增量是会发生变化的,如何优化呢?
对于一条边,其两个端点在不同连通块,其分别加入两个连通块的集合,然后在一个连通块中生效(生效:加入后删掉该连通块与(1)的边)
用set启发式合并维护这个过程
(O(mlog^2m))
Random Knapsack
肯定是考虑哈希碰撞,预处理(B)个,(O(B+qfrac{mod}{B}k))(其中(k)是哈希的常数)。取(B=10^6)能过(20)分
考虑预处理(2^{20})个,排序后两两之和期望情况下大概是(16000)级别的,如果能过第三个点,那结合那种算法是能过的
不过我并不知道怎么过第三个点
考虑将(16000)分开做,先将([0,2^{10}))这些数查询子集(这仅需要过第二个点),再单独查询(2^{10},2^{11},2^{12},2^{13},2^{14})
对于查询,具体拿多少个数出来给它们还需要调调参
放份场上的代码code