NOI2020
Day1
美食节
-
这个题一看就感觉是个矩乘,因为数据范围这么大还和走路有关
-
为了保证一次只能走一格的规则,我们需要先处理这个边权
-
这个边权 \(w\leq 5\) 太小了,考虑直接拆了
-
最显著的拆法是将边拆成 \(w\) 段,前 \(w-1\) 段的边权为 0 ,第 \(w\) 段的边权为 \(c_v\) ,代表走完这条路能取得的收益
-
那么现在有 \(5n\) 个点,每次走一条边,问走 \(T\) 条边回到原点能得到的最大收益(暂时不考虑美食节)
-
这个就直接建一个系数矩阵,复杂度是 \(O(n^3\log T)\)
-
再考虑美食节的影响,美食节没办法在矩乘的中间处理,又可以发现美食节的数量也是很小的,考虑每两个美食节之间进行矩乘转移,到达一个美食节的时间时暴力在矩阵上修改
-
那么复杂度是 \(O(k(5n)^3\log T)\) ,这不太优秀
-
我们最终要求的是到原点的最大值,所以实际上我们只用保留第一行的元素,也就是一个长度为 \(5n\) 的序列
-
那么一个显然的优化就是预处理出 \(T\) 二进制下的所有 \(2^k\) 的矩阵,每次用序列和矩阵相乘,这样复杂度就可以降为 \(O(n^2)\) 了
-
那么最终的复杂度就是 \(O(k(5n)^2\log T)\) ,可以通过
总结
-
矩乘 + 二进制优化
-
题目本身还是比较好想的,注意矩阵赋初值时不合法的地方一定要赋值成负无穷,而不是 0 ,不然你就会和我一样调半天不知道哪有问题
命运
-
首先肯定是考虑树形 dp
-
可以发现对于对于每个点的每一条以这个点为下端点的链,我们只关心上端点最深的链
-
通过这个,我们可以发现对于一个点和它的子树,我们只关心祖先中最深的还没满足条件的点的深度
-
设 \(dp[x][i]\) 表示下端点在 \(x\) 子树中,没有满足条件的上端点中最深的节点的深度为 \(i\) 时的方案数
-
特殊的,\(dp[x][0]\) 表示全部满足条件时的方案数
-
现在考虑合并上子节点的答案
-
假设 \((x,v)=1\) ,那么 \(dp[x][i]=\sum_{j\leq dep[x]} dp[v][j]\times dp[x][i]\)
-
假设 \((x,v)=0\) ,那么 \(dp[x][i]=\sum_{j\leq i} dp[v][j]\times dp[x][i] + \sum_{j<i} dp[x][j]\times dp[y][i]\)
-
写成前缀和的形式,就会发现要么是常数项,要么是有关于下标 \(i\) ,那么线段树合并就可以了
总结
-
树形 dp + 线段树合并
-
实际上这个树形 dp 才是这个题目真正的难点,线段树合并还是比较好写的
时代的眼泪
-
注意到每一个位置的纵坐标组成了一个排列,说明值域 \(\leq 10^5\)
-
题目抽象出来,其实就是要求一个区间在一个值域中的正序对的个数
-
考虑用序列分块套上值域分块来做这个东西
-
将贡献分成整块之间,整块和散块,散块之间的贡献,分别去解决就可以了,整体的思路还是比较好想的
-
你问我代码?下次一定
Day2
制作菜品
-
首先考虑 \(n=m\) 的情况,一定有答案,因为一定有一个位置的数字 \(\leq k\) ,那么拿掉这个,再从最大的身上拿掉剩下的,就还剩 \(n-1\) 个原材料和菜品,又是一个相同的子问题,递归下去一定有解
-
然后会发现 \(m\geq n\) 时也一定有解
-
再考虑 \(m=n-1\) 时,此时仍然可以考虑拿走一个 \(\leq k\) 的原材料,然后从最大的里面拿走剩下的,通过计算可以证明一定存在这种方案,也就是变成了相同的子问题,最终可能会剩下 1/2 个原材料,仍然符合题目的要求,所以 \(m=n-1\) 的情况也一定存在解
-
最后考虑 \(m=n-2\) 的情况,可以发现无法再按照上面的思路去思考了,考虑将这种情况分成两个 \(m=n-1\) 的情况,也就是构造一组子集 \(|S|\) ,满足 \(\sum d_i=(|S|-1)k\) ,剩下的自然构成另一个子集,那么这两个子集分别对应两个 \(m=n-1\) ,也就是如果能构造出这样的一种子集,一定有解
-
考虑将这个式子转换一下,\(\sum (d_i-k)=-k\) ,这个显然可以用 01 背包来判断有没有解,因为我们只需要知道是否有解,所以拿
bitset
优化一下,复杂度就是 \(O(\frac{n^2m}{w})\) -
最后还需要考虑证明如果无法构造出这样的集合,就无解,本人目前还没办法证明,
不过你在考场上谁管你证不证明啊,毕竟富贵险中求