2021.7做题记录

P4331 [BalticOI 2004]Sequence 数字序列

首先考虑要求 \(b_1\leq b_2\cdots\leq b_n\) 怎么做
对于一段区间,他是单调不降的,那么显然 \(b_i=a_i\)
对于一段区间,他是单调下降的,那么显然 \(b_i=a\) 的中位数
所以我们把序列分成连续的单调下降的区间,然后对于每一个 \(mid(i)>mid(i+1)\) 我们把这两个区间合并在一起,变成一个新的中位数
这个过程可以按顺序加入,用单调栈实现
考虑维护中位数的过程,本质上是合并两个堆,pop最大值,利用左偏树实现
回到本题,我们发现 \(|a_i-b_i|=|(a_i-i)-(b_i-i)|\),所以我们把 \(a_i-i\),相应的最优的 \(b_i\)\(-i\),这个时候 \(b^\prime_i\) 就是单调不降的了
code

P3273 [SCOI2011]棘手的操作

看到后面 6 个操作,自然的想到如果每一个连通块里面的点都是连续的话,那么就可以用线段树实现了
所以我们把询问离线,按照合并的顺序,每次合并 \(x,y\) 的时候开一个新的节点作为他们的父亲,最后可以建出一个 \(2n\) 个点(左右)的一棵树,这个时候按照叶子结点的顺序,就可以保证每个连通块的位置的编号在一起了,这个过程不难利用并查集来实现
code
\(\mathcal O(n\log n)\)
同样这道题也可以利用左偏树实现
我们把标记打在每个的根上面,每次不下传标记,访问一个位置的值直接用 \(a_i+tag[rt]\)
这个时候合并会出现问题,所以我们可以考虑启发式合并,每次把大小小一些的左偏树的标记暴力下传,这样下传标记的复杂度也是一个 \(\log\)
这样剩下的操作就非常简单了,再开一个可删堆维护每个左偏树的根的最值即可
\(\mathcal O(n\log n)\)

\(\color{red}{复习左偏树时可以再写一遍}\)

CF571C CNF 2

显然如果一个变量只出现了一遍,那么显然他那个位置可以满足
如果一个变量出现了两遍,并且他们都是 x 或者非 x,那么这两个位置都可以满足
接下来我们把出现了两遍的 \(x\)\(-x\) 之间连边,现在要给每条边定向,让每个点至少有一个入边
如果不存在环,显然不行
如果存在环,环上随便定向,非环的往外定向就可以了
难度主要在于代码。。。

code

P6453 [COCI2008-2009#4] F

注意到,对于全局最小值的位置,我们可以把它两边的元素分开考虑
所以不难想到建立一棵笛卡尔树,用 \(f[u][i]\) 表示在 \(u\) 字数上的位置已经放了 \(i\) 个的方案数

\[f[u][i]=\sum_{k=0}^iF(r[u]-l[u]+1-(i-k),a[u]-a[fa],k)\sum_{j=k}f[lc][j-k]\times f[rc][i-j] \]

其中 \(F(n,m,k)\) 表示 \(n\)\(m\) 列的矩形放 \(k\) 个的方案数,即为 \(\binom{n}{k}\binom{m}{k}k!\)
注意到 sigma j 的部分可以 \(\mathcal O(n^3)\) 预处理,所以整体转移就是 \(\mathcal O(n^3)\)

code

P6144 [USACO20FEB]Help Yourself P

显然要排序,但是按照 l 还是 r 呢?
注意到如果按照 r 的话有可能让复杂度变小
但是如果按 l 排序,我们每加入一条线段,复杂度要么 +1 要么不变
所以我们用 \(f[i]\) 表示最右边的线段最右边在 \(i\)
每加入一条线段,\(f[r]\) 应该等于 \(f[1...l-1]\) 的和每一个增加1,和 \(f[l...r-1]\) 的和
对于 \(i>r\) 的部分,这条线段选不选对复杂度没有影响,所以直接乘2
不难发现我们可以用一个线段树来维护
注意到 \(x^k\to (x+1)^k\) 不太好维护
我们把 \(\sum x^i\) 全维护一下,利用二项式定理更新即可

code

P3244 [HNOI2015]落忆枫音

首先如果不加边,答案就是 \(\prod inde[i]\)
如果加边形成了一个环,我们要把环的答案减掉,就是 \(\prod_{i\not\in circle} inde[i]\),转化一下,就是 \(\dfrac{\prod inde[i]}{\prod_{i\in circle}inde[i]}\)
考虑从 \(t\) 出发开始在环上做 dp, \(f[v]=\dfrac{\sum_{f[u]}}{inde[v]}\)
答案就是 \(\prod inde[i]-f[s]\)
code

CF1466G Song of the Sirens

对于一个询问串 \(q\),我们设他在 \(s_i\) 中出现了 \(f_i\)
显然有 \(f_i=f_{i-1}+val(s_i,q)\),其中 \(val(s_i,q)\) 表示的是包含 \(t_{i-1}\)\(q\)\(s_i\) 中的出现次数
不难发现这个东西的长度是 \(O(|q|)\) 的,所以我们可以暴力跑 kmp
注意到,对于 \(|s_{i-1}|>|q|\) 的全部 \(s_i\),这些串都是相同的,所以我们可以直接枚举中间那个 \(t\) 是哪个字母,然后直接计算贡献
对于第一个 \(|s_i|>|q|\),我们同样吧 \(t_{i-1}\) 放到中间按照上面的方式跑就可以了

\(\mathcal O(|s|\log |s|+|s|)\)

code

AT2000 [AGC002F] Leftmost Ball

\(f[i][j]\) 表示放了 \(i\) 个白球和 \(j\) 种颜色的方案数,\((i\geq j)\)
对于下一个空位,我们枚举他放的是白的还是新的颜色
如果是白的,直接转移量为 \(f[i-1][j]\)
如果是其他的颜色,这个颜色有 \((n-j+1)\) 种选法,剩下有 \(nm-(j-1)(m-1)-i-1\) 个位置要放 \(m-2\) 个,直接组合数转移就可以了
code

P4774 [NOI2018] 屠龙勇士

显然可以很轻松的求出用哪把刀打这只怪,设这个伤害为 \(b_i\)
那么现在相当于解同余方程组 \(b_i x\equiv a_i(\bmod p_i)\)
对于每一个,我们可以用 exgcd 找到最小的解
假设显然有 \(b_ix_0+p_iy_0=a_i\),注意到两边可以同时对 \(\dfrac{p_i}{\gcd(b_i,p_i)}\) 取模(结合先除gcd再成 \(a_i\) 理解)
所以这个式子等价于 \(x\equiv x_0(\bmod \dfrac{p_i}{\gcd(b_i,p_i)})\)
于是就变成了 excrt 板子了

code

BJSC 2021 Day3-A

显然对于每个班的人从小到大排序
不难猜到 \(1,2\) 做一个桌子,\(3,4\) 做一个桌子......
所以可以枚举每个位置用那个桌子
注意到对于每一个位置,这并不是单谷的
但是对于整体,我们把桌子排序之后是决策单调的
所以直接分治即可

code

loj #2392. 「JOISC 2017 Day 1」烟花棒

我们的目标显然是让烟花燃放的时间更长
所以设 \(k\) 要把火传给 \(k+1\),那么我们可以对着跑,然后跑到一起之后,一起跑向下一个人,等到 \(k\) 要死的时候再传给 \(k+1\)
所以相当于是从 \(k\) 开始往两边做合并,每次合并的时候可以增加燃放时间为 \(T-cost\)
我们要求燃放时间一直是正的
不难发现,把 \(r\) 合并上 \(r+1\) 的时候增加的答案是 \(\dfrac{X[r]-X[r+1]}{2v}+T\)
所以我们二分 \(v\),接下来的问题是有没有一种构造方案
我们现在可以提取出两个数列 \(a,b\),我们每新取一段,显然这一段的和要 \(\geq 0\),并且还要满足在这一段中间燃放时间的最小值要 \(\geq 0\),否则还不如先取别的
这样我们可以取到两个序列的前缀最大值位置(如果取不到就是 false)
剩下的部分怎么办呢?
我们发现前缀最大值一定是后缀最小值,所以我们从后往前再做一遍看能不能满足条件就可以了

code

posted @ 2021-07-01 19:07  YuukiYumesaki  阅读(50)  评论(0编辑  收藏  举报