2021.1~2做题记录
目录
正文
P2050 [NOI2012] 美食节 | 费用流
首先可以发现第 \(i\) 个厨师做他的第 \(j\) 个菜,时间可以表示为 \(j\times t\)。于是可以把厨师分成 \(mp\) 个点 \((i=1\dots m,j=1\dots p)\)。当 \((i,j)\) 被增广的时候,才加点 \((i,j+1)\),减少边数。用最大流控制所有菜都被做,然后用最小费用求出最小时间和。
P1169 [ZJOI2007]棋盘制作 | 动态规划、单调栈
第一问略。
对于第二问,先预处理出每个点向上、向左、向右最远能合法到达的长度,记作 \(uv_{i,j},lv_{i,j},rv_{i,j}\)。可以发现最终答案的竖向长度一定在 \(uv\) 中。于是枚举行 \(i\) 列 \(j\),用单调栈求出每个 \(uv_{i,j}\) 向左最远到 \(k\) 才会满足 \(uv_{i,j}>uv_{i,k}\),向右亦然。然后就可以通过 \(lv_{i,j}\) 和 \(k\) 求出向左的最大矩形了。
For(i,1,n){
stk.top=0;
For(j,1,m){
while(stk.top&&uv[i][stk.s[stk.top]]>=uv[i][j]) --stk.top;
chkmax(ans2,min((j-stk.s[stk.top]),lv[i][j])*uv[i][j]);
stk.s[++stk.top]=j;
}
stk.top=0;
Dec(j,m,1){
while(stk.top&&uv[i][stk.s[stk.top]]>=uv[i][j]) --stk.top;
chkmax(ans2,min((stk.top?stk.s[stk.top]:m+1)-j,rv[i][j])*uv[i][j]);
stk.s[++stk.top]=j;
}
}
P1654 OSU! | 期望 dp
发现这个 \(x^3\) 的 combo 分数不太好做,于是先考虑 \(x\) 和 \(x^2\) 怎么做。
记 \(a_i\) 为前 \(i\) 次操作,连续的操作贡献 \(x\) 的分数的、以 \(i\) 为结尾的 combo 的期望。则显然有 \(a_i=p_i(a_{i-1}+1)\)。
记 \(b_i\) 为贡献 \(x^2\) 的期望,则有 \(p_i\) 的概率会比 \(b_{i-1}\) 多贡献 \(2a_{i-1}+1\) (根据完全平方公式可得)。则 \(b_i=p_i(b_{i-1}+2a_{i-1}+1)\)。
仿照 \(a_i,b_i\),可以得出 \(f_i=(1-p_i)f_{i-1}+p_i(f_i-1+3b_{i-1}+3a_{i-1}+1)\),即有 \(p_i\) 的概率比 \(f_{i-1}\) 多 \(3b_{i-1}+3a_{i-1}+1\),有 \((1-p_i)\) 的概率不变。这样 \(f_n\) 就是答案了。
P6858 深海少女与胖头鱼 | 期望 dp
首先考虑一个比较暴力的想法:设 \(f_{i,j}\) 为有 \(i\) 条带圣盾的,\(j\) 条不带圣盾的,期望需要打几次。
那么 \(f_{i,j}=\dfrac{if_{i+j-1,1}+jf_{i,j-1}}{i+j}+1\)。可以发现我们只需要用到 \(f_{i,1}\) 和 \(f_{n,j}\)。如果我们能够在 \(O(1)\) 的时间内计算出 \(f_{i,1}\),那么问题就被解决了。
推式子得 \(f_{0,1}=1,f_{i,1}=f_{i-1,1}+i+2\)。通项公式显然为 \(f_{i,1}=1+2i+\frac{i(i+1)}{2}\)。
于是我们就可以在 \(O(m \log 998244353)\) 的时间复杂度内完成此题。
P3980 [NOI2008] 志愿者招募 | 费用流
建模十分巧妙。
假设一开始有 \(\inf\) 名志愿者。那么我们需要把最大流限制为 \(\inf\),即所有志愿者都需要到终点。
对于第 \(i\) 天和第 \((i+1)\) 天中间连一条流为 \(\inf-a_i\),费用为 \(0\) 的边,代表这些志愿者可以不干活过去。
对于每个 \((s,t,c)\) 连边 \((s,t+1,\inf,c)\),代表这些志愿者需要付费让他们过去。
跑费用流。
AcWing 206. 石头游戏 | 矩阵加速
首先,因为操作序列长度不超过 \(6\),且最多有 \(10\) 种,所以每过 \(60\) 秒,所有位置的操作序列都会和 \(60\) 秒之前的一样。
于是可以算出 \(60\) 个转移矩阵 \(A_{1\dots 60}\),每个矩阵都是 \((nm+1)\times (nm+1)\) 的。对于每种操作分别处理一下即可。
这里有一个很巧妙的思路:用多出来的那一行记录常数项,这样加石子的时候会很方便。即,令 \(A_{1\dots60,nm+1,nm+1}=1\)。
算出 \((\prod A_{1\dots60})^{t/60}\),再用矩阵乘法补齐剩下的 \(t\bmod 60\) 即可。
UVA11149 Power of Matrix | 矩阵乘法、分治
https://www.luogu.com.cn/blog/alan-zhao/solution-uva11149
P3254 圆桌问题 | 二分图多重匹配
略。
考试的时候写错了一个地方,丢人。
P4016 负载平衡问题 | 费用流
略。
AcWing226 233矩阵 | 矩阵加速
考虑把同一列的东西放在一个矩阵里面。构造转移矩阵的时候,可以把同一列的元素之间的加法转化为前缀和。
P6569 [NOI Online #3 提高组] 魔法值 | 矩阵加速、倍增
构造 \(0/1\) 矩阵,证明其乘法具有结合律。然后倍增预处理 \(A^{2^k}\),每次进行二进制拆分即可。
P5490 【模板】扫描线 | 线段树
这题的线段树可以通过神奇的 Pushup 操作来避免懒标记。具体可以见《算法竞赛进阶指南》中“线段树”一节。