day2
简单dp
A
首先枚举时间 \(t\),\(t\in[0,\max b_i-\min a_i]\),然后对于每个人 \(i\) 可以求出一个行李的范围,这个范围的行李满足:这些行李到达 \(b_i\) 的时候,时间都大于等于 \(t\)
然后不难发现一个单调性:
如果把人按照位置从小到大排序,那么后面的人的范围肯定包含前面的人的范围
因此考虑对于人从前往后 dp ,令 \(f[i][j]\) 表示前 \(i\) 个人选择了 \(j\) 个行李的方案数,假如对于第 \(i\) 个人而言,有 \(g[i]\) 个行李可能够到他,那么就有转移:
C
首先确定一下策略:
对于一个人 \(i\),会选定一个 \(j\),然后把 \(j\) 左边的都往左一个一个地合并到 \(i\) ,右边同理
然后不难注意到一个性质:
性质1:
对于每个 \(i\) 从左/右合并过来的值至多有 \(\log\) 个
所以记 \(l[i][j],r[i][j]\) 表示 \(i\) 从左/右合并过来的能够达到第 \(j\) 个值的最靠左/右的位置是多少,然后进行二分即可。时间复杂度为 \(O(n\log^2n)\)
B
这个题手玩一下可以注意到一个性质
性质1:
如果将首尾相接的节目看成一个个块,那么最优策略中则存在某一种将一个个块再进行割分的方式,使得割分完的每个块要么起始位置踩在关键点上,要么结尾位置踩在关键点上
然后朴素的状压dp即可
D
考虑二进制下的比较,先通过操作把 \(a\oplus b \ge k\) 转化为 \(a\oplus b > k\)
那么意味着至少存在一位使得 \(a\oplus b\) 与 \(k\) 是不同的
然后考虑在 \(trie\) 进行树上背包,为保证不重不漏,我们钦定每一个匹配在第一位与 \(k\) 不同的那个位置被计算即可,所以有状态 \(f[i][j]\) 表示以 \(i\) 为根的树里,已经(用掉 \(j\) 个 \(a\) 来)和 (((与 \(i\) 配对的那个点 \(lnk[i]\) )的子树里)的 \(j\) 个 \(b\) )进行匹配的方案数,然后朴素转移即可
E
首先注意到这个解的结构,就是分成上下两个部分
然后从前往后dp的过程中维护一个相对大小的顺序,每次加入数字的时候就是把元素插入到这个相对大小中即可。具体的,令 \(f[i][j]\) 表示前 \(i\) 个值里,上面的元素有 \(j\) 个,下面的元素有 \(i-j\) 个的情形下,逆序对最多是多少
不过还需要判断有无交集,需要使用一个并查集来处理,时间复杂度为 \(O(n^2)\)
F
注意到性质:
性质1:
你操作不会超过 \(\log\) 次
性质2:
你操作的范围一定是在笛卡尔树上的
所以放在笛卡尔树上进行dp即可,令 \(dp[i][j]\) 表示在以 \(i\) 为根的子树里使用了 \(j\) 次操作后,序列中最大值的最小值是多少,然后进行朴素的转移即可,时间复杂度 \(O(n\log^2 n)\)
G
神奇乱搞题
H
简单题,你只需要注意到序列 \(s\) 满足以下条件
(1) \(s\) 的最大值要么在最左边要么在最右边
(2) \(s\) 只有一个最大值
(3) \(s\) 去掉最大值得到的序列 \(s'\) 也是好的
因为事实上 \(f(i)\not = f(j)\iff f(i)>f(j),i>j\)
所以从大往小dp即可,具体的,令 \(dp[i][j]\) 表示目前最小值为 \(i\) 且最大公因数为 \(j\) 的序列数量,然后动态维护一下前缀和:\(sum[x]=\sum_{i}dp[i][x]\)
考虑转移:
对于 \(i\) 枚举加入 \(i\) 后最大公因数变成了 \(d\) ,这个时候需要求出 \(\sum_{\gcd(x,i)=d}sum[x]\)
直接枚举会爆掉,但是注意到 \(x\) 是 \(d\) 的倍数,因此可以把 \(sum[x]\) 改为 \(\sum_{\substack{i\\x|y}}dp[i][y]\)
但是这样求出来的只能保证最大公因数是 \(d\) 的倍数,所以可以考虑像前几天讲的一样,拿莫反处理一下就行了
所以时间复杂度是
可以通过本题
I
不难发现其实第 \(i\) 位的一个芯片就相当于第一个位置的 \(fib[i]\) 个芯片,其中 \(fib[i]\) 表示斐波那契数列的第 \(i\) 项,所以考虑一个过程:把所有的位置的芯片都转移到 \(1\) 上,再重新分配,所以假如第 \(i\) 个位置上有 \(x_i\) 个芯片,那么如果 \(\sum x_i\cdot fib[i]\) 相等,那么答案相等
所以考虑实际上累加到第一位的总和不会超过 \(n\cdot fib[10]\le 90000\) ,所以只需要对每一种可能的总和进行 \(dp\) 即可,这是一个完全计数背包
另外一方面,还需要计算每一种可能的总和的成本是多少,这个也可以使用 \(dp\) 来完成,具体的,令 \(cost[i]\) 表示总和为 \(i\) 时的成本是多少,那么有
J
我知道有人是拿 \(O(1024n)\) 通过的,但是其实有更优美的解法
考虑 \(x^2\) 有什么意义,可以将 \(x\) 进行二进制拆分,假如 \(x=\sum_{i=0}^9bit[i]\cdot 2^i\)
那么 \(x^2=\sum_{i=0}^9\sum_{j=0}^9bit[i]\cdot bit[j]\cdot 2^{i+j}\) ,考虑对于每个有序对 \((i,j)\) 统计其期望的贡献即可,
这是因为因为 \(\mathbb E(\sum_{i=0}^9\sum_{j=0}^9bit[i]\cdot bit[j]\cdot 2^{i+j})=\sum_{i=0}^9\sum_{j=0}^9\mathbb E(bit[i]\cdot bit[j])\cdot 2^{i+j}\)
所以实际上的时间复杂度为 \(O(n\log ^2V)\)
K
对于除了第一行的每一行而言,第一位玩家不能有剩余,就是如果给每一行赋值 \(+1/-1\) 其中 \(-1\) 代表二号玩家的牌,\(+1\) 代表一号玩家的牌,那么每一行的每一个前缀和均不小于 \(0\) ,然后第一行的情况恰好相反,同时,还要记录一下除了第一行外其余的行第一位玩家欠了第二位玩家多少个卡,然后在第一行一起算上
M - 神奇的贪心dp
首先二分答案,然后把每个元素转换成 \(0/1\)
然后题目就是要求每次去掉连续的 \(k\) 个,实际上我希望去掉的 \(0\) 尽可能多,所以我令 \(f[i]\) 表示 \(1\sim i\) 至多能去掉多少个 \(0\) ,\(g[i]\) 表示 \(i\sim n\) 至多能去掉多少个 \(0\) ,然后通过前缀和优化进行朴素的 \(dp\) 转移即可
关于正确性:
这个 \(dp\) 状态里并没有保证选的块的个数,但是事实上由于 \(f[i],g[i]\) 都是最优的,所以不可能会允许存在 \(\ge k\) 个位置是没选到的,也就是说 \(f[i],g[i]\) 的最优性天然保证了能去掉足够多块
至于为什么要两个数组,这是因为需要处理 \(k|n\) 的情形,要保留 \(k\) 个不选,就意味着至少存在一个位置是没选到的,所以答案是 \(\max_{1\le i\le n}\{f[i-1]+g[i+1]\}\)

浙公网安备 33010602011771号