\[\large \text{Round 11 : Cqbz Weekly Round 13} \]
一言:
男人从小的时候就是无药可救的。
——秋之回忆
炸裂的一场,主将中的最低分,组长中的倒二。
忏悔啊!
\(\text{D : card}\)
写这道题没什么别的意义所在,只是为了记录一下回退背包的知识点。
这个题目可以非常容易的转化为在所有除去 \(a_i\) 的数所构成的集合中,与 \([k-a_i,k-1]\) 没有交集。
显然,我们可以暴力枚举 \(i\),然后打一个 \(nk\) 的 0/1 背包。
但是这样的复杂度是 \(n^2k\) 的,所以考虑优化。
我们发现,如果我们求出了 \(1-n\) 所有 \(a_i\) 的 0/1 背包,我们对于枚举到的每一个 \(a_i\),实际上就是将 \(a_i\) 从这个背包中删除。
由于在 0/1 背包中,你的 \(a_i\) 的枚举顺序是无关大雅的,所以想成可以把 \(a_i\) 放在最后一个转移,那么就有 \(dp[j]+=dp[j-a[i]]\),并且 \(j\) 是倒叙枚举。
那么要把 \(a_i\) 删掉,那就考虑正序枚举,然后 \(dp[j]-=dp[j-a[i]]\)。
那么这道题实际上就解决了。
(考场上打的 \(nk\log n\) 的神奇二分做法,被卡到90分。)
\(\text{F : open}\)
算是这几次周考代码最少的 T6,但感觉是思维难度最高的。
首先你需要想到一个非常重要的转化。即我们可以求出任意两个传送门之间互相到达的最短距离,然后题目就转化为了求传送门之间的最小生成树。
于是,你得到了重要的前 \(60pts\)。
那么如何优化呢?
我们考虑一个构造生成树的过程,回顾一下 \(\text{kruskal}\) 算法。
对于每次操作,实际上我们都是找到两个还没有联通的传送门中,距离最小的连在一起。
那么考虑将任意一条边拆解为图中最原始的边。
然后对于途中的任意一条边 \((x,y)\),求出 \(x,y\) 分别到距离最近他们的传送门的距离 \(dis_x,dis_y\),那么这条边实际的贡献就是 \(w(x,y)+dis_x+dis_y\)。这一步可以考虑多源最短路。然后根据 \(\text{kruskal}\) 的思想,考虑将任意边按照他们的贡献排序,每次连一条边,就是将他们对应的两个传送门连接在一起,最后输出连的边的贡献和。
至于为什么这样是对的,额俺也不会证,俺也不知道。可以理解为,如果没有选择这条边,那么就必然可以将新选的这条边拆解为另外的边,但他们的贡献更少(或者出现了环之类的东西)。
毕竟重点是猜结论,赛时很难证明的。。
\(\text{What I learned}\)
-
如果你需要算除开 \(a_i\) 的一些信息,考虑对动态规划进行回退(例如背包,当然有些无法回退)。
-
如果是 \(n\) 个点,每个点都要用一次,且每个点可以使得另外一个点配合上会产生一个与这两个点信息有关的权值,可以任意配合,考虑生成树。
-
对于生成树上的边,如果是由很多条基本边合在一起的,可以考虑将他们拆解开。