October Challenge 2020 Division 1

打了两次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+q\frac{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

posted @ 2020-10-08 10:57  Grice  阅读(162)  评论(0)    收藏  举报