为了分别 OI 与日常,这里只会放些我认为比较好的题,其他题应当在学习笔记中。
to do list
- 多项式杂烩 (doing)
- LCT ?
- 仙人掌(2024.9.18)
- 一些较难的 DP
- 构造 与 ad-hoc
- 博弈论(不会打表找规律) : (
- 推式子练习
- 计算几何 ?
- PAM,
广义SAM- Kummer 定理
2025.1.7
在平面直角坐标系求大小确定的矩阵所可能包含的最多点数,可以扫描线。
在有 \(\mathrm{mex}\) 的题目中,可以考虑暴力枚举 \(\mathrm{mex}\),AT_arc156_b Mex on Blackboard。
谨防诈骗题,构造题,AT_arc156_c Tree and LCS。
咋找的题都是我的弱项啊,容斥好弱啊,这么简单的都没咋想出来...,AT_abc200_e Patisserie ABC 2。
看到一个 Kummer 定理的东西,加入 to do list。
I ARC156D Xor Sum 5
极其好的题,有很大的启发性。
异或有一个相消的性质,即若对于长度为 \(k\) 的序列 \((p_1,p_2,\cdots,p_k)\),考虑其翻转序列 \((p_k,p_{k-1},\cdots,p_1)\),其 \(\sum a_{p_i}\) 是相等的,可以相消,除非其与其翻转序列相等,即为 回文序列,所以我们只需要考虑求回文序列 \(P\) 的异或和。
- 若长度 \(x\) 为 偶数,则可以直接拆成两部分后,两部分的 \(\sum a_{p_i}\) 是相等的,则有 \(f_x = 2f_{\frac x 2}\)。
- 若长度 \(x\) 为 奇数,则我们需要考虑加上中间一位的贡献,然后转化为偶数的情况,一个想法是直接把需要整体加的数记下来。
则可以设 \(f_{i,j}\) 表示对于所有长度为 \(i\) 的序列 \(P\) 中,\(j + \sum a_{p_i}\) 的异或和。
- 对于偶数 \(i = 2x\),有 \(f_{2x,j} = 2f_{x,\lfloor\frac{j}{2}\rfloor} + (nj \bmod 2)\)。
- 对于奇数 \(i = 2x+1\),我们需要枚举中间项,有 \(f_{2x+1,j} = \displaystyle\bigoplus_{i=1}^n 2f_{x,\lfloor\frac{j + a_i}{2}\rfloor} + (n(j + a_i) \bmod 2)\)
如果你不是很理解的话,你需要知道 异或 对于 \(2\) 的次幂的乘法是具有分配的,即 \(2^k(x \bigoplus y) = (2^kx) \bigoplus (2^ky)\)
首先第一维是只有 \(\log k\) 的,第二维大小最大是 \(\max a_i\) 的,转移 \(\mathcal{O}(n)\)。
总复杂度 \(\mathcal{O}(n\max a_i \log k)\)。
该题启示我们对于要求的特殊性,及时排除不需要讨论的答案。
代码
2025.1.8
额额额,先做了点 CPU,[民间数据练习场] THUSC 2023 Day2 奋斗四小时,手搓 CPU。
I [ARC144C] K Derangement
你说的对,但是我的构造就是使。
无解是好判断的:\(2k > n\),因为中间的点没有可行位置。
首先我们贪心的选,让每个点移动越近越好,考虑每 \(2k\) 个数分为一组,则可以正好每个数移动 \(k\) 次,即 \((1,\cdots,2k-1,2k) \Rightarrow (k+1,\cdots,2k,1,\cdots,k)\),但是显然不能分完,考虑最后 \(2k\) 个数怎么分。
最后 \(k\) 个数是好分的,一定在 \(i - k\) 的位置上,因为其可行位置本来只有 \([n - 2k + 1,i - k]\),然后把剩下的数从小到大填进去,合法是显然的,且由于从小到大填,字典序也有保障。
遇到式子中带绝对值且要求最大值时,可以直接拆掉绝对值。
2025.1.9
在遇到边权只有 \(0/1\) 的图中,可以考虑去除掉无用边,CF2057E2 Another Exercise on Graphs (hard version)。
看了点容斥的课,以及简单复习了下拉插,奇妙反演。
I P3270 [JLOI2016] 成绩比较
首先恰好 \(k\) 位同学被碾压不好求,考虑反演,设 \(f(i)\) 表示钦定 \(i\) 位同学被碾压的方案数,\(g(i)\) 表示恰好 \(i\) 位同学被碾压的方案数,有。
然后考虑 \(f(k)\) 怎么求,每个课程是独立的,可以先只考虑一个,最后将所有课程的方案数乘一起即可。
设当前课程最高分为 \(U\),\(B\) 神排名为 \(R\),则除了我们钦定的 \(k\) 个人分数比 \(B\) 神小,还存在 \(n - 1 - (R - 1) - k\) 个人分数比 \(B\) 神小,有 \(\dbinom{n - 1 - k}{n - k - R}\) 种方案,然后我们可以枚举 \(B\) 神此课程的分数,即 \(\displaystyle\sum_{i=1}^Ui^{n - R}(U - i)^{R - 1}\),这样枚举是基于值域的,考虑怎么优化,先推下式子。
左边可以直接枚举,右边是一些自然数次幂和的形式,可以直接拉插。
前半部分复杂度是 \(\mathcal{O}(n^2)\) 的,后半部分仅与每门课程相关,复杂度 \(\mathcal{O}(n^3\log{n})\)。
总复杂度 \(\mathcal{O}(n^3\log{n})\),但是这个傻子懒,拉插写的 \(\mathcal{O}(n^2)\),总 \(\mathcal{O}(n^4)\),也能过。
自己犯的几个错误:二项式定理没拆 \(-1\)(上述框住的),打代码拉插的 \(y\) 没乘(难绷)。
代码
2025.1.10
I [ARC101E] Ribbons on Tree
在容斥中的一些子集可以用同一个 DP 状态表示,即可考虑用 DP 来求容斥的贡献。
首先考虑考虑暴力容斥,枚举边的子集,将这些边钦定为无颜色边,则树被分为几个连通块,对于一个大小为 \(x\) 的连通块,若 \(2\mid x\),则其贡献为 \((x - 1)!!\),否则为 \(0\)。
即 \(ans = \displaystyle\sum (-1)^{|T|}\displaystyle\prod_{i=1}^{|T|}(T_i - 1)!!\)
指数显然是不行的,注意到容斥求贡献时只与联通块的大小相关,所以可以考虑 DP,设 \(f_{x,j}\) 表示在以 \(x\) 为根的子树中,当前 \(x\) 所在连通块大小为 \(j\) 时的容斥贡献。
则在枚举子树 \(y\) 时,若当前边钦定为无颜色边,则有 \(f_{x,j} \gets f_{x,j} \times f_{y,k} \times (-1) \times (k - 1)!!,2 \mid k\),\((-1)\) 是多的容斥系数,否则是树包。
感觉和 NOIP2024 T3 非常像,唉...。
复杂度 \(\mathcal{O}(n^2)\)。
代码
II P3349 [ZJOI2016] 小星星
首先可以状压,设 \(f_{i,j,now}\) 表示 \(i\) 所对应的节点为 \(j\) 且当前子树内已选子集为 \(now\) 的方案数,枚举子集是 \(\mathcal{O}(n^33^n)\) 的。
貌似可以优化,我不会。我们可以考虑来降低一些限制,然后通过容斥求解。
我们要求的是每个节点唯一被对应的方案数,所以我们需要有 \(now\) 的状态,考虑去掉该限制,可以 \(\mathcal{O}(n^3)\) 求解,然后我们枚举子集,钦定未被对应的节点,容斥下,即 \(ans = (-1)^{|T|}f(\overline{T})\)。
复杂度 \(\mathcal{O}(n^32^n)\)。
代码
III P7481 梦现时刻
考虑直接求出 \(F\),不会卷积,只能硬推。
考虑右式。
考虑框中式子。
综上得到:
复杂度 \(\mathcal{O}(n^2)\)。
代码
IV CF451E Devu and Flowers
多重集的组合数,就是裸的容斥。
满足的第 \(i\) 个限制是 \(s_i \leq f_i\),\(ans = \left|\displaystyle\bigcap_{i=1}^n S_i\right| = (-1)^{|T|}\left|\displaystyle\bigcap_{i=1}^{|T|}\overline{S_{T_i}}\right|\)。
考虑第 \(i\) 个限制的补集为 \(s_i \geq f_i + 1\),我们可以用总数减去,这样是等价的,转化为了 \(s - \displaystyle\sum_{i=1}^{|T|}f_{T_i} + 1\) 个花中分成 \(n\) 堆,插板法可得答案为 \(\dbinom{s - \displaystyle\sum_{i=1}^{|T|}(f_{T_i} + 1) - 1 + n}{n - 1}\)。
复杂度 \(\mathcal{O}(2^nn)\)。
注意组合数会爆 longlong
,要先取模再乘。
代码
2025.1.11
I P2167 [SDOI2009] Bill的挑战
考虑二项式反演转化为钦定问题,设 \(f(i)\) 表示钦定与 \(i\) 字符串匹配的方案数,枚举子集,可以 \(\mathcal{O}(2^nn|S|)\) 简单求。
反演得 \(g(k) = \displaystyle\sum_{i=k}^n(-1)^{i-k}\dbinom{i}{k}f(i)\)。
总复杂度 \(\mathcal{O}(2^nn|S|)\)。
代码
2025.1.16
today : 思维题选讲
感觉 md 除了细节还是细节,这就是我们思维题吗,
代码难度可太低了。
I CF1775E The Human Equation
我们对该序列做个前缀和,考虑操作变成了什么,第一类操作相当于将一些子序列都加了 \(1\),第二类类似。
则我们归结为了可以选择一个子序列加/减 \(1\),只需找到 \(> 0\) 中最大的,以及 \(< 0\) 中最小的即可。
复杂度 \(\mathcal{O}(n)\)。
代码
II QOJ # 8939. Permutation
大意:交互,你可以询问区间 \([l,r]\) 中次大值的位置,让你求出最大值的所在位置,询问次数 \(\leq \lceil1.5\log{n}\rceil\),询问区间总长度 \(\leq 3n\)。
首先有一个比较基础的想法,对于一个区间 \([l,r]\) 我们找出了其次大值的位置 \(p\),我们进行二分,若 \(p \in [l,mid]\),则我们询问 \([l,mid]\),若询问答案为 \(p\),则代表最大值就在 \([l,mid]\) 中,否则我们需要重新考虑(额外多询问一次) \([mid+1,r]\) 区间中的次大值,这样二分,可以达到询问次数 \(2\log{n}\),考虑进一步优化。
当查询答案为 \(p\) 时我们询问的次数比另一种情况少,考虑平衡这个东西,即进行三分四分114514分,对于 \(t\) 分,我们将 \(p\) 所在位置定为较大的分区间,则询问次数为
假设 \(f(n) = k\log{n}\),则有 \(k\log{t} + 1 = k\log{1 - t} + 2 = 0\),解得 \(t = \dfrac{\sqrt{5} - 1} 2,k = -\dfrac{1}{\log{\frac{\sqrt{5} - 1}{2}}} \approx 1.44\)。
所以我们只需要 \(0.618\) 分就可以了!
代码
III CF1477C Nezzar and Nice Beatmap
一个结论:对于一个点,我们找离他最远的点当下一个即可,因为三角形中最长边的两边角一定为锐角。
复杂度 \(\mathcal{O}(n^2)\)。
IV CF2053D Refined Product Optimality
显然两数组排完序对应最大,修改有一万种 \(\log\)。
V gym104768 B. The Game
\(A\) 中最大的 \(m\) 与 \(B\) 对应,因为大小相等的可以等价操作。
然后先进行不必要的操作,在进行对应,可以用 \(set\) 维护,细节蛮多的。
复杂度 \(\mathcal{O}(n\log{n})\)。
代码
VI QOJ # 6503. DFS Order 3
给出从 \(n\) 个节点开始的 \(dfs\) 序,还原树。
对于每个节点 \(dfs\) 序最大的一个点,一定为原树的叶子,这样我们考虑找到叶子,叶子中 \(dfs\) 序最小的点即为其父亲,每次操作完删去这些叶子。
这样可以做到均摊 \(\mathcal{O}(n^2)\)。
代码
VII CF1696F Tree Recovery
给出的相等关系比较弱,考虑假定原树中存在 \((x,y)\) 这条边,则我们可以推出整个图,这样是 \(\mathcal{O}(n^5)\) 的。
考虑到枚举所有边是没有必要的,因为经过 \(1\) 的一定存在一条合法边,则我们只需要枚举 \((1,x)\) 即可。
复杂度 \(\mathcal{O}(n^4)\)。
代码
VIII QOJ # 9586. 野兽节拍
考虑到对于每个长度为 \(3\) 的字符串,其合法位置是均摊 \(\mathcal{O}(n)\) 的,则我们每次删掉 \(3\) 个点,可以用链表维护。
总复杂度 \(\mathcal{O}(n)\)。
锐评:纯纯的大漠你。对了,记得字典序 : (
代码
IX CF1442D Sum
直接暴力 DP 是 \(\mathcal{O}(nk^2)\)。
考虑到一个结论:在所选的数组中,最多只有一个数组没被选完。
证明:设数组 \(a,b\) 正好选到 \(i,j\),有 \(a_i < a_{i + 1},b_j < b_{j + 1}\)。
不妨设 \(a_i < b_j\),则不选 \(a_i\) 改选 \(b_{j+1}\) 更优,即最后只会剩下一个数组没有选满。
则我们可以考虑哪个数组没有选满,剩下的是背包。
可以分治做,具体的,在考虑 \([l,r]\) 区间内,我们加入 \([l,mid]\) 中的物品,递归到 \([mid+1,r]\) 中,还原后加入 \([mid+1,r]\) 中的物品,递归到 \([l,mid]\) 中。
这样当递归到 \([l,l]\) 时即为除了 \(l\) 这个物品,其他物品的背包数组。
复杂度 \(\mathcal{O}(nk\log{n})\)。
代码
2025.1.17
I [ABC255G] Constrained Nim
公平组合游戏,考虑求其 \(SG\) 值。
直接求显然不行,考虑特殊点单独求,复杂度 \(\mathcal{O}(m\log{n})\)。
普通点即为一些斜率为 \(1\) 的直线。
代码
2025.1.19
today: 高级数据结构
因为太难写了,导致笔记延期了。。。
I CSA Baby Seokhwan
大意:给定 \(n\) 个 \(m\) 维向量,初始都为 \(0\),有 \(q\) 个修改 \([l,r,p,x]\) 表示将 \([l,r]\) 中的向量第 \(p\) 维设为 \(x\),不会在同一位置操作多次,求出 \(n\) 个向量的字典序排名,相等编号小的靠前。
考虑用主席树维护 \(n\) 个向量,每个修改可以拆成 \([l,p,x]\) 与 \([r+1,p,-x]\),只有单点修改。
然后我们可以正常排序,用主席树哈希找出两个向量的 \(\mathrm{lcp}\),用来比较字典序大小。
复杂度 \(\mathcal{O}(n\log^2{n})\)。
代码
II P6109 [Ynoi2009] rprmq1
\(\max\) 没有可减性,不好维护。
考虑扫描 \(x\) 这一维,用线段树维护 \(y\),对于一段询问 \([l1,r1]\) 相当于求出 \([l1,r1]\) 中线段树上 \([l2,r2]\) 的历史最大值。
然后可以直接考虑线段树分治,但是直接将询问拆成 \(\log{n}\) 个复杂度会爆。
考虑在一个最大的分界 \(mid\),分别向左右考虑,这样的分治结构叫做猫树分治,或者二区间合并。
具体来说,在区间 \([l,r]\) 中首先我们已经加入了 \([1,l-1]\) 的修改(不考虑历史最大值)。
先考虑询问的右部分 \([mid+1,r]\) 的答案,先加入 \([l,mid]\) 的修改,然后依次考虑 \([mid+1,r]\) 的历史最大值,递归到右半部分,然后需要撤销 \([mid+1,r]\) 的修改,再进行考虑 \([l,mid]\) 的部分,依次撤销 \([l,mid]\) 的修改(倒序),求出历史最大值,最后递归到左半部分。
线段树需要 历史最大值 以及 还原 的操作,前半部分这里不说,对于还原,我们考虑在额外维护一个 \(tag\),当为 \(1\) 时将 \(tag\) 下传,并还原历史最大值。
总共分了 \(\log{n}\) 层,修改总共是 \(\mathcal{O}(n\log{n})\) 的,查询单个是 \(\log{n}\) 的。
总复杂度 \(\mathcal{O}(n\log^2{n} + q\log{n})\)。
代码
III LOJ #6679. Unknow
李炒熟不可删,不能直接扫描线。
考虑链上怎么做,可以考虑分治,消去不可删的影响,或者说可以直接叫线段树分治,直接分治也可以,不过利用线段树的结构更好写。
分治后可以直接上李超树,复杂度 \(\mathcal{O}(n\log^3{n})\)。
可以更优,考虑李超树插入 2log 的原因是因为插入的是一条线段,可以进而对 \(x\) 进行分治,消去线段的影响,可以当成直线,这样就可以不用李焯书了,维护一个凸包,可以简单做到线性,复杂度 \(\mathcal{O}(n\log{n}\log{X})\)。
考虑上树,比较 native 的想法是直接暴力树剖,套个树套树,呃,太劣了,考虑树剖的一个性质,一条 \(u \to v\) 的路径一定是一些重链前缀加上一段任意区间,考虑将每个线段加到重链首,在加上上述链的做法。
总复杂度 \(\mathcal{O}(n\log{n}(\log{n} + \log{X}))\)。
这个傻呗 2log 没调出来,代码复杂度是 \(\mathcal{O}(n\log^3{n} + n\log^2{n})\),也过了。
代码
IV UOJ #218. 【UNR #1】火车管理
考虑主席树维护每个时间下每条铁路栈顶的进入时间。
用另一颗线段树维护答案,操作 \(1\) 是好办的,操作 \(2\) 可以在主席树上查询当前铁路的进入时间 \(t\),则 \(t-1\) 就是下一个栈顶所在时间,可以直接查询位置,进行修改,操作 \(3\) 相当于在主席树上区间覆盖,这里有一个 Trick:可以直接 ls[p] = rs[p] = p
。
总复杂度 \(\mathcal{O}(n\log{n})\)。
代码