9 月做题记录
学习一下 KTT,很牛啊。
已知有 \(n\) 个一次函数 \(k_ix+b_i\),有 \(m\) 个询问,每次询问 \(\max_{i=1}^n \{k_ix_j+b_i\}\)。
做法其实很多,比如整体二分,李超线段树啥的。
这 \(n\) 个函数,随着 \(x_i\) 的增大,观察函数相对大小的变化,发现最多会变化 \(O(n^2)\) 次,难以直接维护。
注意到建成一颗线段树的形式,将一堆函数分成两半,如果左边右边都已经有序,那么中间相对位置的改变只会有 \(O(n\log n)\) 次,也就是和归并排序一样。
具体来说,因为要找最大值,维护左右两个区间里面当前最大的那个函数,然后随着 \(x_i\) 的修改如果左右最大的函数的大小关系发生变化就暴力修改。
为什么只需要取最大值呢,因为子区间里面如果有一个函数变成最大,就会先变成这个子区间里面的最大值,这个可以通过不断 push up 维护。
这样只需要记录左右子区间,小的那个还需要加多少才能超过大的那个,然后超过了就暴力递归修改,总共修改 \(O(n\log n)\) 次,总复杂度 \(O(n\log^2 n)\)。
如果只是这里显然没啥用,注意到这个的厉害之处在于可以修改,可以支持对一个函数的单点修改,这是李超线段树做不了的,修改之后一样上传,复杂度应该还是 \(O(\log^2 n)\) ???
CF1823F \(\color{green}\bigstar\) *2600
发现一个 link,对着做一段时间。
简单题,设 \(f_{i,j}\) 表示 \(i\) 出发,到 \(j\) 的期望次数。
但是这样很混乱,因为一直随机游走,连设方程都不方便。
和树上随机游走类似,把行走过程划分成一个个阶段。
假设 \(s\to t\) 的路径是 \(a_1\to a_2 \to ... a_k\),那么划分成 \(k\) 个部分,每个部分向父亲走一步就进入下一个阶段。
那么状态变成 \(f_{i,j}\) 表示 \(j\in \text{subtree}(i)\),\(i\) 走到 \(fa_i\) 之前经过 \(j\) 的次数。
分析一下简单情况, \(f_{i,i}\),每次到 \(i\),有 \(\dfrac{1}{d_i}\) 的概率向上,否则进入子树,进入子树后肯定又会回到 \(i\),因此 \(f_{i,i}=d_i\)。
分析一下 \(f_{i,j}(j\in \text{son}(i))\),得到 \(f_{i,j}=\frac{f_{i,i}}{d_i}f_{j,j}=d_j\),归纳一下发现 \(f_{i,j}(j\in \text{subtree}(i))=d_j\)。
所以答案只要算一下一个点父亲有多少个在 \(s\to t\) 的路径上,答案就是 \(d_i\times f_i\),时间复杂度 \(O(n)\)。
其实是可以带修的,瞎胡一下可以支持删点加点,查询 \(\{s,t,x\}\)。
CF1830F *3200 \(\color{Gold}\bigstar\)
发现一个点的贡献只和右边第一个选的点有关。
设 \(f_i\) 表示 \(i\) 选了,\(i\) 前面点的总贡献最大值。
\(w(i,j)\) 表示包含 \(i\),不包含 \(j\) 的区间个数,那么这个扫描线后相当于只有区间加。
因此直接 KTT 维护区间加 \(p_j\) 即可。
CF1517F *3200 \(\color{blue}\bigstar\)
最大半径就是离他最近的 \(0\)。
如果直接设 \(f_{i,j}\) 表示 \(i\),半径是 \(j\) 比较困难,因为上面也要满足,而且子树里可能有更大的。
枚举一个 \(r\) 求半径 \(\ge r\) 的方案数,这样变成判定性问题。
设 \(f_{i,j,k}\) 表示 \(i\) 子树内,最深的目前满足条件的点深度为 \(j\),离 \(i\) 最近的 \(0\) 距离为 \(j\),合并是树上背包合并,复杂度 \(O(n^5)\),爆炸,前缀和优化后是 \(O(n^4)\)。
注意到,如果存在一个 \(j\),那么此时 \(k\) 是无意义的,因为必然不会影响其他子树,因为 \(j+k>r\)。
所以两维不会同时有用,直接记录两个 \(f_{i,j},g_{i,j}\),树上背包合并 \(O(n^3)\)。
loj2494 \(\color{Gold}\bigstar\)
非常好题目,赞美 HNOI。
一开始想了一个做法,就是从后向前,那么当前要求前缀一些位随意,一些位必须是 \(0/1\),然后就可以从后向前推,注意到出了最后一次,前面要求必须的位要么全是 \(0\),要么全是 \(1\),因此可以 bitset,复杂度 \(O(\frac{Qnm}{w})\),不知道能不能过。
对于每一位,把 \(1\) 放前面,\(0\) 放后面,那么当前有要求的一定是个区间。
考虑对于一位具体是咋搞的,如果最后是 \(1\),然后填或就直接是 \(1\),否则就无影响,相当于一个二进制的比较。
因此做法就简单了,排序一下,然后答案就是相邻两个二进制相减。
loj2495 \(\color{Gold}\bigstar\)
小丑题。
答案显然就是
一开始想了个分块做法,不知道能不能过。
事实上这个东西只和后缀最大值有关,直接楼房重建就行。
loj2496 \(\color{green}\bigstar\)
非树边拉出来容斥,然后求一个独立集个数。
可以动态 dp,但是那样 \(m-n\) 可以开更大,这题正解是比较好写的虚树,只要维护每条链的系数就行。