202510做题记录
加粗斜体表示思考时被卡了的部分。
打 \(*\) 的表示做过的重新想(做)一遍。
打 \(^?\) 的表示看了题解。
打 ~ 的表示还没做 / 还没写上来。
特别的,\(^!\) 和 \(*^?\) 都表示做过一遍还是不会 😦
按时间查找
如果发现链接是空的,那么请在其他文章里查找。
10/01
ARC199 A~B
MX-NOIP-R11C
10/02
AGC005 D~F
CF2134F
10/03
AGC036F
MX-NOIP-R12C
MX-NOIP-R12D
CF2152 A~G
10/04
CF2152 H1H2
ABC426G
10/05
ARC207 A~C
MX-NOIP-R11D
10/06
CF2038 D 见 ARC207 C。
CF2145 A~G
JOISC2024-Day2 C
10/07
ARC207 D
AGC006 C
10/08
MX-NOIP-R13C
MX-NOIP-R13D
AGC006 D-E
10/09
AGC006 F
AGC007 C~E
10/10
MX-NOIP-R14A
MX-NOIP-R14B
MX-NOIP-R14D
AGC007 F
AGC008 B~C
CF1450H2
CF2153A~F
10/11
ARC199 C
HT-NOI081-A
HT-NOI081-C
10/14
ARC140 D
ARC204C
ARC208D
HT-NOI081-B
10/15
AGC009D~E
ARC201E
P7880
MX-NOIP-R15A
MX-NOIP-R15B
MX-NOIP-R15C
10/17
MX-NOIP-R16A
MX-NOIP-R16B
MX-NOIP-R16C
AGC010D~E
10/19
10/20
MX-NOIP-R16D
AGC011C
AGC010F
AGC019F
10/21
MX-NOIP-R17A
MX-NOIP-R17B
MX-NOIP-R17C
MX-NOIP-R17D
ARC198D~E
ARC197E
10/22
好困啊好困啊好困啊好困啊好困啊好困啊
AGC011 D~F
10/23
10/24
MX-NOIP-R18A
MX-NOIP-R18B
MX-NOIP-R18C
MX-NOIP-R18D
CF2018B
CF2018F1~F3
ARC196B
10/25
10/27
HT-NOIN016-A
HT-NOIN016-B
AGC074C
P8528
CF1383E
CF830D
10/28
AGC012C~F
HT-NOIN016-C
CF1615F
CF1626F
10/29
MX
NOIP R11
C
P10230
注意到三角剖分可以和树的结构对应。要求的就是询问一个 \(x\),问以 \(x\) 为根的树的拓扑序。
前置知识:\(T=(V,E)\) 的拓扑序个数为 \(\dfrac{|V|!}{\prod_{i\in V}sz_i}\)
于是每次修改三角剖分,等于修改树的结构。
考虑快速维护。考虑树其实是三角剖分的对偶图。于是三角剖分的一条线,在树上有一条对应的跨越边。
考虑按照这个计算贡献。如果根在线的某一侧(设为 A 侧),那么另一侧(B)的那个点,对根的贡献是已知的。
具体的,如果线的 B 侧包含了 \(a\) 个点(不包括端点),那么树 B 侧的点的子树大小就是 \(a\)。这样,这个点对 A 侧的根的贡献就是 \(\frac{1}{a}\)。
于是,和树的形态无关,只和加入的每条边有关。所以可以方便地修改。使用树状数组维护每个点的贡献。
NOIP R12
D
把 \([1,l)\) 的 BST 建出来,然后 \([1,l)\) 的子树节点集合已经确定。
然后假设有了 \([l,r]\) 的方案,我们可以立刻得到 \((r,n]\) 的位置。具体的,一个点 \(x\) 所属的子树是 \(a_x\) 所属的 \([1,r]\) 中按 \(a\) 切割出来的,段的两侧的深度较大的那个点的子树。
然后这种东西可以 \(O(n^3)\) 区间 dp 做。
然后虽然转移不是那么标准,但是大胆猜测有决策单调性。过了。
NOIP R13
C
设 \(a_i\) 表示点 \(i\) 是第 \(a_i\) 个点亮的。
考虑容斥。我们称一条边 \((u,v)\) 不合法,当且仅当 \(|a_u-a_v|=1\)。
然后不合法的边构成的一定是一些链。也就是点的不合法边度数 \(\leq 2\)。
如果有 \(k\) 条不合法边,构成了 \(c\) 条链,那么方案数是 \((n-k)!2^c\)。
然后我们只要在 dp 的过程中维护有几条不合法边,链的 \(2^c\) 的贡献在转移的时候做就可以了。
具体地,\(f(i,j)\) 表示 dp 到 \(i\),\((i,fa_i)\) 是否不合法的方案数。
然后转移是树上背包,一维是不合法边数,另一维是有几条不合法边要接入当前点。
D
可能有不那么难写的做法。 有更好写的做法。
考虑暴力怎么做。
固定 \(t\),那么有 \(f(s,t)=\min(E(t)+k,d(s,t))\)。
其中 \(d(s,t)=dep_s-dep_t\) 当且仅当 \(s\) 在 \(t\) 子树内。否则为 \(\inf\)。
\(dep\) 表示到根路径上的 \(\sum p\)。
然后又 \(E(t)=\operatorname{avg}(f(*,t))\)。
于是经过一些推导,我们有 \(\sum_s\max(E(t)+k-d(s,t),0)=kn\)。
这可以在维护下标是 \(d(s,t)\) 的树据结构上二分求出。
然后维护因为值域比较大,动态开点线段树不好做,可以使用 fhq-treap 有交并,以及 fhq-treap 上二分做到 \(O(n\log V)\)。
考虑怎么求。注意到固定 \(s\),\(t\) 从 \(s\) 到根,\(E(t)+k-d(s,t)\) 会在一个分界点 \(x\) 到根的链上 \(\leq 0\)。
于是我们在 dfs 的过程中,使用可并堆维护子树节点,并且不断尝试弹出 \(dep\) 最大的。如果堆顶是 \(x\) 且 \(E(t)+k-d(x,t)>0\) 则可以弹出 \(x\)。
然后是计算答案。\(ans_s=\sum_t f(s,t)\)。
考虑 \(f(s,t)=d(s,t)\) 的情况,当且仅当 \(d(s,t)<E(t)+k\)。这可以在 dfs 的过程中维护祖先的 \(dep\) 来快速求出。
然后是 \(f(s,t)=E(t)+k\),也是好求的。
然后其实做完了。需要注意的是可能要卡常。最后一步维护 \(dep\) 可能要离散化加树状数组。
复杂度 \(O(n\log V)\)。写了 5k。
复杂度 \(O(n\log n)\)。
NOIP R14
B
首先,特判掉 \(r-l+1<5\) 的情况。。这里暴力做。
然后是 \(r-l+1\geq 5\)。发现这时候有结论,设 \(h\) 是 \(a_l,\cdots,a_r\) 的最高位,如果有 \(k\) 个 \(a_i\ (i\in[l,r])\) 的最高位是 \(h\),那么:
- \(k\) 是奇数,最后答案是 \(2^h\)。
- \(k\) 是偶数,答案为 \(0\)。
于是前缀和记录一下每一位的出现次数,然后注意到固定 \(r\),\([l,r]\) 的最高位只会变化 \(O(\log V)\) 次。所以直接枚举最高位,复杂度 \(O(n\log V)\)。
C
比较牛的 dp。考虑自顶向下展开这颗树。
我们每次拓展深度 \(h\) 最大的点:
- 可以拓展出 \(h-1,h-1\) 两个点。
- 可以拓展出 \(h-1,h-2\) 两个点。
也就是,只跟最上面两层未拓展的点的个数有关系。
所以 \(f(i,j,k)\) 表示上面两层 \(i,j\) 个点,有 \(k\) 个不平衡。
枚举 \(c\),有 \(f(i,j,k)\binom{i}{c}\to f(j+2i-c,c,k+c)\)。
我们正常 dp 要枚举所有状态,不太好,考虑记忆化搜索。这样状态数是 \(O(n\log n\log^* k)\) 的。
然后考虑 \(f(i,j,k)\) 意味着当前点及其之前的树的结点个数是 \(2i+j-1\) 个。
所以最后要的其实只是 \(2i+j-1=n\) 的状态。所以倒着从这些状态搜。复杂度 \(O(\log n\log^5 k)\)。?
D
求最大子段和最基础的方法就是 \(f(i)=\max(f(i-1),0)+a_i\),答案是 \(\max_i f(i)\)。
这个方法的优点在于,只需要加一个 \(a_i\),以及和另一个大整数比较。
这种东西在 CF464E The Classic Problem 里出现过。
比较麻烦的是减去一个数,这样我们要维护退位,也就是要区间赋值 \(1\)。所以要多维护一个区间赋 \(1\) 标记,下传的时候,因为是可持久化的,所以要新开儿子节点。
复杂度 \(O(n\log V)\)。
NOIP R15
C
首先有显然的整除分块。这里令 \(A=\sum a_i,B=\sum b_i\)。
但是要分 \(\sqrt A=O(n)\) 块,每一块要 \(O(n)\) 计算显然不行。
但是注意到单点计算只要 \(O(\log n)\)。
然后继续注意到,对于形如 \(n/m\) 的整除分块,如果 \(m>b\),则一定分出 \(\leq\frac{n}{b}\) 个块。
于是根号分治。对于 \(x\leq b\),有 \(O(b\log n)\),反之有 \(O(\frac{A}{b}n)\)。(设 \(A,B\) 同阶)
于是令 \(b=\sqrt{\frac{An}{\log n}}\)。平衡得到复杂度 \(\sqrt{An\log n}\)。
NOIP R16
C
对于字符串的长度为 \(k\) 的最小子序列,有贪心做法:对于第 \(i\) 个字符,找到在第 \(i-1\) 个之后,在位置 \(r-(k-i)\) 及之前的最小字符的第一个位置。
考虑最后串一定形如 \(c_a\times\texttt{a}+c_b\times\texttt{b}+\cdots+c_X\times\texttt{X}+suf\)。 其中 \(X\) 是某一个字符,\(suf\) 是 \(s[l,r]\) 的一个(可空)后缀。
于是我们可以倍增优化找 \(c\) 和 \(suf\) 的过程。复杂度 \(O(q|\Sigma|\log n)\)。
然后对于最后两个 \(suf\) 的比较,要二分哈希或者 SA。
复杂度 \(O(n\log n+q|\Sigma|\log n)\)。
D
超级大粪、、题解写的依托。做法也是依托。
考虑根据弱化版 P7841 的思路,我们 dp 子树的 SG 值。
首先注意到一条链的 \(SG=len\bmod 2\)。
一般的,枚举子树中第一次选择的边,那么到根的部分是一条链,下方是一个子树,这两个子问题的 \(SG\) 使用 \(\operatorname{xor}\) 合并。
有 \(SG(i)=\operatorname{mex}_{j\in subtree(i)}(SG(j)\operatorname{xor}(dep_j-dep_i-1\bmod 2))\)。
注意到 SG 最多是 \(O(\log n)\) 的。直接 dp 可以通过弱化版。
考虑进一步观察性质。我们发现这样的 SG 转移,子树根节点已经包含了子树的一些性质。
具体的,如果一个儿子 \(SG=x\),那么根节点 \(SG\geq x\operatorname{xor} 1\)。因为 \(SG\) 更小的一定在子树中。
在此基础上我们发掘性质,发现:
- 如果存在 \(k\) 使得每个儿子 \(SG\leq 2k+1\),且存在 \(SG=2k,SG=2k+1\) 的两个点,那么这个点 \(SG(x)=2k+2\)。
- 否则 \(SG(x)=\max_{i\in son(x)}SG_i\operatorname{xor} 1\)。
于是我们的转移只和儿子有关系了。
注意到 Alice 先选择一个点,其实就是要求一个子树内、外两部分,换根后的 \(SG\) 值。考虑加速换根过程。
注意到换根后,\(SG\) 有变化的只在原来的根到新根的路径上。
根据 \(SG\) 只有 \(O(\log n)\) 的性质,我们思考直接在树上从原来的根开始,每次暴力跳到 \(SG\) 下一次变化的位置,复杂度是对的。
向上跳随便维护。问题是向下跳的方向怎么定。考虑树剖,默认向下跳重儿子。这样切换轻儿子的步数也是 \(O(\log n)\) 的。
于是我们预处理 \(pos(i,j),tv(i,j)\) 表示 \(i\) 点,\(SG=j\) 时,向上跳到 \(pos(i,j)\),\(SG\) 会变成 \(tv(i,j)\)。
同理,预处理 \(pos2,tv2\) 表示沿着重链向下跳。
于是大力分类讨论即可。复杂度 \(O((n+q)\log n)\) 而且比 std 做法的常数小到不知道哪里去了。
Fun fact:这个做法的 \(O(n\log^2 n+q\log n)\) 实现,速度是单 log std 的 2 倍。\(O((n+q)\log n)\) 实现的速度是 std 的 3 倍。不知道 std 在写什么。
NOIP R17
B
根号分治。考虑:
-
\(k_i\geq B\) 先 \(O(A/k_i)\) 暴力做掉。
-
\(a<B\),此时对于 \(f\),预处理 \(f(t)\bmod c(c<B)\) 的所有情况。记录到桶里。查询枚举 \(k\)。复杂度 \(O(qB)\)。
-
\(a\geq B\)。此时注意到我们枚举合法的 \(k\)(即 \(kt\leq A\)),复杂度是调和级数 \(O(A\ln A)\) 的。于是枚举倍数,以及合法的 \(k\),复杂度 \(O(A^2/B\ln A)\)。
取 \(B=\sqrt{n\ln n}\),复杂度 \(O(A\sqrt {A\ln A})\)。
C
考虑计算每个值靠左的那个位置的贡献。然后倒着做一遍。
对 \(r\) 扫描线。然后考虑左侧出现了一次的值的位置集合 \(S\),找到最大次大值 \(a,b\),则合法 \(L\in (b,a]\)。
然后考虑出现了两次的值集合 \(V\)。设 \(l_v,r_v\) 表示 \(v\) 两次出现的位置。
那么 \(\forall v\in V,L\not\in [l_v,r_v]\)。
使用平衡树暴力维护即可。当然存在一种集合哈希的线性做法。
D
考虑如果固定 \(T_1\) 以 \(1\) 为根,那么有 \(f(x,y)\) 表示 \(T_1(x)\) 和 \(T_2(y)\) 的子树匹配。
然后转移的时候,对于 \(f(x,y)=1\) 当且仅当 存在一个 \(T\) 到 \(S\) 的单射 \(p\),使得 \(S=son(x),T=son(y),\forall t\in T,f(p(t),t)=1\)。
直接跑二分图匹配的复杂度是 \(O(n^{2.5})\),加上枚举 \(T_1\) 的根,复杂度 \(O(n^{3.5})\)。
当然要考虑换根啦。
换根的时候,要注意不能每向一个儿子转移就重跑匹配,这样复杂度不对。而是要找二分图匹配的必经点做判断。
复杂度 \(O(n^{2.5})\)。
NOIP R18
B
操作了前 \(i\) 个点,此时第 \(i\) 个点的可能值只有 \(O(\log n)\) 个。具体地,只有其祖先或祖先的兄弟可能被交换过来。
于是我们直接设 \(f(i,j)\) 表示 操作前 \(i\) 个点后,第 \(i\) 个点的值是 \(v(i,j)\) 的最优情况。
然后分类讨论。对于 \(i\) 最小或者其左儿子最小的情况,操作是唯一的。
考虑右儿子最小。此时左右子树一定是 \(v_i,v_{ls}\) 各选一个。分类讨论:
- 如果 \(v_i<v_{ls}\)。那么考虑往某棵子树走后,\(v_i\) 会走到哪个点。我们发现显然编号越小越好。否则 \(v_{ls}\) 选这个位置,值一定更大。所以具体设 \(f(i,j)\) 表示 \(v(i,j)\) 最后会走到的点即可。
- 否则就是 \(v_{ls}\) 走到的编号越小越好。也就是 \(v_i\) 要走的是 \(v_{ls}\) 不优的那个子树。
转移是简单的。复杂度 \(O(n\log n)\)。
C
懒得喷。直接观察得到,枚举最小的边长 \(x\),那么其他两边 \(y,z\),要么 \(z-y\) 最小,要么 \(z-y\) 尽可能大。
对于 \(z-y\) 最小随便做。考虑尽可能大。
继续观察,我们枚举 \(z-y=d\),那么对于相同的 \(d\),只关心最小的 \(z\)。
正着不好做,考虑反着贡献。
于是枚举 \(d\),找到尽可能小的 \(>d\) 的边长。现在的瓶颈是找到 \(z-y=d\) 的最小 \(z\)。
使用 bitset 做到 \(O(n^2/w)\)。。
D
直接暴力做呗。考虑每次归并会影响什么。
注意到归并会把一个前缀最大值和其后面的一串较小值直接放进新串。所以我们用前缀最大值为分割。
找到当前序列的前缀最大值。设其领导的段是到下一个前缀最大值之前。
我们发现只有跨过 \(n/2\) 的前缀最大值领导的段,才会被切开。
然后这两个新段的归并,只有被切开后新增的段会对答案有影响。并且最后都是升序排序。
于是直接上 fhq-treap 维护。考虑分析操作次数。注意到,如果当前段不是归并操作的不动点,那么一次操作至少会多一个段。所以最多操作 \(n\) 次就可以到达不动点。
复杂度 \(O(n\log n)\)。注意维护不要把复杂度弄假了。
HT
NOI 081
B
有意思。很牛啊。
考虑朴素 dp,\(f(i,j)\) 表示两个人当前时间是 \(i,j\)。
然后挑选较靠前的人转移。
我们发现,不妨假设 \(i<j\),此时 \(f(i,j)\leq f(i,i)+1\)。因为 \(f(i,j)\) 的上一次转移一定是从 \(j'<i<j\) 转移来的。
那么不转移就是 \(f(i,j')\leq f(i,i)\leq f(i,i)+1\)。
这个性质非常强。 此时,我们发现,固定较小的一维(设为 \(i\)),那么 \(f(i,j)(j\geq i)\) 只有两种值 \(f(i,i),f(i,i)+1\)。
对于 \(f(i,j)=f(i,i)(j>i)\) 的,显然不优。不考虑。
我们只考虑最小的 \(f(i,j)=f(i,i)+1(j>i)\)。
所以我们只关心 \(f\) 最大是多少。在此基础上再最小化第二维。
于是记录 \(f(i)[v,x]\) 表示值,位置。
然后转移类似之前的暴力。但是需要注意要 \(f(i,i)\)。也就是 \(f(i,i)=f(i)[v]-1\)。然后做转移。
复杂度线性。
* C
注意到每次选择的答案增长是凸的。
所以考虑 wqs 二分,然后每次暴力在线段树上合并 dp 值。我们只要记录每个节点左右端点是否选择情况下的 dp 值。
复杂度是 \(O(n\log^2 n\log V)\) 的。看起来不太能过。
然后这样每次都要二分的玩意,考虑整体二分。我们对线段树的结点维护一个指针。每次整体二分查询的时候,只是移动这个指针找最优解。然后发现这样可以均摊掉一个 \(\log\)。复杂度 \(O(n\log n\log V)\)。
NOI N016
B
简单。一条边要么在环内,要么在环外绕一圈。称为边的状态。
考虑如果两条边的区间相交,那么这两条边一定状态不同。
所以使用带权并查集维护。
直接暴力维护的复杂度是平方的。然后卡时输出 Yes 即可通过。。
当然不能这么暴力。
考虑扫描线。对于靠后的那个区间,找到和他相交的前面区间。
那么前面区间 \([x,y]\) 用线段树做一个区间 \((x,y)\) 加颜色,然后对于后面区间 \([l,r]\),是一个单点查询 \(l\) 位置的颜色,然后合并这些颜色,并且和 \(l\) 状态不同。
这种东西可以简单的在线段树上维护。复杂度是均摊正确的。因为一个节点的所有颜色在被合并过一遍后,只会留下一种颜色。所以每种颜色会额外被访问 \(O(1)\) 次。每次加颜色会覆盖 \(O(\log)\) 个节点,所以复杂度 \(O(n\log n)\)。
luogu
LGR 246
B
设 \(dep_i\) 为 \(i\) 深度。\(mxd_i\) 为 \(\max_{j\in\text{subtree(i)}}dep_j\)。
不妨枚举第一个点的位置 \(u\),那么我们发现对于 \(2\sim k\) 这些点,都要有 \(dep_i=dep_u\),且 \(mxd_i\geq mxd_u\)。
然后还有要求是剩下的树的 \(mxd\geq mxd_u\)。
于是枚举 \(dep\),然后对于相同 \(dep\) 按照 \(mxd\) 排序。枚举 \(dep_u=dep\),然后其他点要求 \(mxd\) 更大,且至少有一个 \(mxd=mxd_u\) 的。
一种显然的情况是,\(\exists i,dep(b_i)=dep_u\)。此时方案数组合数随便算。
然后是 \(\not\exists i,dep(b_i)=dep_u\),此时要求 \(dep=dep_u,mxd>mxd_u\) 的点的个数恰好是 \(k-1\) 个,且 \(dep=dep_u,mxd=mxd_u\) 的个数 \(\geq 2\) 个。
C
糖丸了。不是很麻烦做法写+调了 80min。怎么会是呢。
一种做法是,只维护不被其他操作偏序的集合(一个轮廓),这样加入一个区间,会删除后面的一些区间。使用 set 维护,每次暴力删除,复杂度均摊 \(O(n\log n)\)。
我们发现查询一个区间,答案只能是:和轮廓相交的位置,或者是轮廓的凹处。
然后用线段树维护两个相邻区间相交的位置(凹处)的值。
复杂度 \(O(n\log V)\)。。
然后发现其实还有一种做法,直接维护 \(x=i\) 的位置,\(y\) 最大的区间是 \(v_i\) 什么。然后是区间 \(\text{chmax}\)。
查询注意到 \(v_i\) 单调,在线段树上二分答案。然后每个节点同时维护 \(v_i-i\) 的最小值。做一个区间查询即可。。
D
很厉害。赛时没写完正解。
把三种出招看做 \(0,1,2\),然后 \(i+1\bmod 3\) 胜 \(i\)。
一种做法是考虑 agc052e 的转化,然后发现不是前缀最大值、后缀最大值的地方都会有 \(1\) 的贡献。
是前、后缀最大值的位置,可以观察发现,设最大值对应的 \(a\) 是 \(u\),最优方式一定是选择所有的 \(u\) 或 \(u+1\bmod 3\)。
然后对着这个嗯做。然后巨大复杂。
简单做法:首先显然对于 \(a_i=a_{i-1}\) 的,先操作掉一定不劣。
然后接下来 \(>\) 表示 \(a_i\) 胜 \(a_{i+1}\)。\(<\) 反之。
类似第一种做法的结论,对于相邻的 \(><\),一定可以删除,并且让答案 \(+1\)。
对于连续的 \(>>>/<<<\),可以删除,并让答案 \(+1\)。
显然先操作 \(><\) 一定更优。
于是我们设 dp,\(f(i,j,k,w)=(f,g)\) 表示 dp 到 \(a_i\);当前 \(>>\) 后缀长度为 \(j\);操作了 \(><\) 后,\(<<\) 的个数 \(\bmod 3=k\);\(a_i=k\) 的方案数,和答案之和。
然后枚举转移:
注意这里 \((f,g)+c\to (f,g+cf)\)。
- \(t=w\):\(f(i-1,j,k,w)+1\to f(i,j,k,t)\)
- \(t=w+1\bmod 3\):
- \(j>0\):\(f(i-1,j,k,w)+1\to f(i,j-1,k,t)\)
- \(j=0\):\(f(i-1,j,k,w)+[k=2]\to f(i,j,k+1\bmod 3,t)\)
- \(t=w-1\bmod 3\):\(f(i-1,j,k,w)\to f(i,j+1,k,t)\)。
答案就是 \(\sum (f(n,j,k,w)+(j/3)+[j\bmod 3=2\land k=2])[g]\)。
计数
AGC036 F
有趣计数。首先无脑容斥,那么变成枚举有多少个不满足的。
首先,思考一个子问题:给你排列 \(a\),有 \(a_i\leq v_i\) 的一些限制,怎么计算方案数。显然按照 \(v\) 排序,从小到大计算。
对于这道题,问题在于怎么找到这个顺序。
注意到,对于 \(0\leq i\leq n\),如果 \(n^2\leq i^2+P_i^2\leq (2n)^2\),那么 \(P_i\geq n\)。
也就是,因为 \(i>n\) 时所有 \(\leq (2n)^2\) 都合法,所以 \(i\leq n\) 的满足要求的情况,一定是最大的,也是最后计数的。
对于 \(i\leq n\) 不满足的,以及 \(i>n\) 的情况,我们直接暴力 dp 做即可。
ARC140 D $^?$
考虑拆贡献。一个图的答案等于图中连通块的个数。于是考虑计算用了 \(k\) 个 -1 的连通块。
注意到最后图的连通块是基环树,所以我们枚举环上有 \(u\) 个点,方案数是 \((u-1)!\)。
先考虑把非 -1 的合并起来。设有 \(m\) 个连通块,有 \(c\) 个 -1。这样我们发现有 \(c\) 个连通块是树。\(m-c\) 个基环树。
所以我们可以把几棵树合并成一颗基环树。具体的,是把每棵树的根向另一棵树的任意一点连边。
考虑设 \(f(i,j)\) 表示 dp 到第 \(i\) 个树,选了 \(j\) 个的方案数。
有 \(f(i,j)=f(i-1,j-1)+sz_if(i-1,j)\)。后一项要乘上选择该树内任意一点的方案数。
然后答案就是 \(\sum_{j=1}^c f(i,j)n^{c-j}(j-1)!\),然后加上已经是基环树的连通块的贡献。
~ P7575 $^?$
想岔子了。一开始莫反奇怪地往枚举 \(\operatorname{lcm}\) 去了。
还是要先直接思考暴力 dp 以及直接的转移。有 \(f(i,j)\) 表示 dp 到第 \(i\) 个,这个数是 \(j\) 的方案数。
于是转移 \(f(i,j)\to f(i+1,k) (\gcd(j,k)=x_i)\)。
重写一下是 \(f(i+1,k)=\sum_{j}f(i,j)[\gcd(j,k)=x_i]\)。
这种东西直接上莫比乌斯反演。
\(f(i+1,kx_i)=\sum_{j}f(i,jx_i)[\gcd(j,k)=1]=\sum_{j}f(i,jx_i)\sum_{d|\gcd(j,k)}\mu(d)=\sum_{d|k}\mu(d)\sum_{d|j}f(i,jx_i)\)。
然后这个 \(x_i\) 看着很烦。那么对于一次 \(i\) 的转移,我们定义 \(f'(j,k)=f(j,kx_i)\)。注意到 \(x_i\) 互不相同,所以状态数是 \(O(n\log n)\) 的。
于是 \(f'(i+1,k)=\sum_{d|k}\mu(d)\sum_{d|j}f'(i,j)\)。
然后看着还是很烦。于是我们预处理 \(g'(j,k)=\sum_{k|w}f'(j,w)\quad\mathbf{[A]}\)。
于是 \(f'(i+1,k)=\sum_{d|k}\mu(d)g'(i,d)\)。
然后再令 \(g''(j,k)=\mu(k)g'(j,k)\)。
于是 \(f'(i+1,k)=\sum_{d|k}g''(i,d)\quad\mathbf{[B]}\)。
硬算是 \(O(n\log^2 n)\)。
然后我们发现复杂度瓶颈 \(\mathbf{[A]}\mathbf{[B]}\) 分别是狄利克雷后缀和、前缀和。
所以用其优化为 \(O(n\log n\log\log n)\)。
CF2030 G1G2 $^?$
考虑中心在每个位置的代价函数。我们发现每个区间对这个代价函数会贡献一个分段凸函数。因为凸的和还是凸的,所以我们可以贪心得到:如果一个位置两侧都不比它优,那么它一定可以作为这个集合的中心。
因为端点重合很难做,所以离散化成不重的。
考虑找到一个比较好作为贡献位置的点。 然后得到,这些线段的端点集合的中位数一定满足要求。
然后考虑拆贡献。 我们枚举在集合中的,不跨越中心的区间,然后组合数稍微算一下就好了。
要注意到的是,\(\binom{x}{i}\binom{y}{i}\),其中 \(c,d\) 是常数时,通过下标取反可以变为狄利克雷卷积形式 \(\binom{x}{i}\binom{y}{y-i}\)。下标加减常数同样如此。
CF2018 F1~F3 $^?$
考虑枚举贡献区间 \([l,r]\)。直接算恰好为 \([l,r]\) 的答案不好做。放宽成包含。然后容斥掉。
考虑包含。那么对于 \([l,r]\) 内的 \(a\),贡献是 \(\prod_{i\in[l,r]}(n-\max(i-l,r-i))\)。
对于 \([l,r]\) 之外的,我们要找到唯一的一种对应方式。
考虑这么一种贪心:我们尽可能向左拓展,如果必须向右再向右拓展一次。显然每种操作和合法 \(a\) 都是一一对应的。
然后 \(f(l,r,0/1)\) 表示按照这个方式拓展了 \([l,r]\),下一步必须向左还是向右的方案数。
然后转移唯一特殊的地方是 \(f(l,r,1)\to f(l,r+1,0)\),此时保证了 \(a_{r+1}\) 是右侧唯一约束向右拓展的位置,所以方案唯一。
对于其他情况的转移,方案数都是 \(n-(r-l)-1\)。
这样做复杂度 \(O(n^4)\)。考虑优化。
我们发现,对于 \(f\) 的转移,只有初值不同,但是要求的结果都是 \(f(1,n,0)\)。这启发我们倒着 dp。
这样免去枚举 \([l,r]\)。复杂度 \(O(n^2)\)。
计数 2
CF830D
套路。记 \(2^i-1\) 子树内的未连接路径条数 \(j\)。dp 状态 \(f(i,j)\) 表示方案数。
那么 \(f(i,j),f(i,k)\) 向 \(f(i+1,j+k+c) c\in\{-1,0,1\}\) 转移。
系数是简单的。要注意的是,\(c=-1\) 时,可以在同一个子树内选择两条路径进行合并。。。。。。。。。调了半天。。。。。。。。
CF1383E
把 \(1\) 之间的 \(0\) 的个数提取出来,变成一个序列 \(a\)。
本质上是对 \(a\) 的子子序列 \(b\) 计数。
子子序列的定义是,可以找到一个单射 \(P\),使得 \(\forall x_1<x_2,P(x_1)<P(x_2)\)。同时 \(b(x_i)\leq a(P(x_i))\)。
相对于子序列,就是把 \(=a(P(x_i))\) 变成 \(\leq a(P(x_i))\)。
所以 dp 方式也是类似的。
在子子序列自动机上进行 dp。思考一下,子序列自动机就是贪心找到下一个匹配的位置。
所以子子序列自动机同理,找到下一个 \(\geq v\) 的位置。
于是记 \(f(i,j)\) 表示 \(P(now)=i,b_{now}=j\) 的方案数。注意到状态是 \(\sum a_i=O(n)\) 的。
然后转移就是 \(f(i,j)\to f(t,k)\),使得 \(a_t\) 是 \(>i\) 的第一个 \(\geq k\) 的位置。
使用前缀和优化 dp。复杂度线性。
dp 小练
CF1437 F
考虑观察整体结构,我们发现一定是从一开始,出现一个 \(v\geq 2premx\) 的,然后接下来又是一段 \(\leq \frac{1}{2}v\) 的。
于是我们根据这个结构最明显的 \(v\) 进行 dp。我们设 \(f(i)\) 表示 dp 到 \(v=i\)。然后下一个位置 \(2j\leq i\)。
然后观察发现得到对于 \([\lceil\frac{1}{2}j\rceil,\lfloor\frac{1}{2}i\rfloor]-\{j\}\) 这些数,一定可以无脑放在 \(v=i\) 位置的后面。
然后我们同时知道,\(v=i\) 后面,当前数的个数是 \(n-\lceil\frac{i}{2}\rceil\)。然后这部分直接组合数。
所以复杂度 \(O(n^2)\)。可以优化到 \(O(n)\)。
CF1806 D
对于排列形式的 dp,一个套路是按照值从小到大(大到小)dp。
套路的,我们考虑从小到大 dp。当然观察题目要求也能想到要这么做。
考虑加入一个数 \(i\),考虑放在之前 \(i-1\) 个数的哪个位置。
如果放在最后面,那么对答案有 \(1\) 的贡献。否则没有贡献。
直接 dp 即可。
怎么总是会被奇怪的地方卡一下。。
数据结构
不是很会这(些)种东西啊。。该练练了。
大部分的题可能是树上数据结构(?
支配对
支配对通常用来解决一类点对贡献问题。具体来说,任意两个对象构成一个点对,我们做一定范围内的信息查询时,就相当于查询范围内的点对的信息并。但是这样点对的数量是 \(O(n^2)\) 量级的,无法接受。
支配对优化这类问题的思想,就是只保留有效点对,通常题目中有性质使得有贡献的点对量级会得到减小。
type I
本质不同的点对个数只有 \(\mathcal O(n)\) 种。
P7880 $^?$
连板子都不会。。wHAT CAN i SAY?
考虑一个点成为 lca 的情况,可以怎么刻画。
想题的时候一直没有想到低于 \(O(n^2)\) 个限制的刻画。怎么会是呢。
有方法是,通过 dsu on tree,在合并两颗子树的时候,得到限制。
具体地,在合并 \(u\) 两个子树的点的时候,对于小子树的点 \(x\),查询在大子树的前驱后继 \(l,r\),那么对于 \(L\leq l<x\leq R\),以及 \(L\leq x<r\leq R\) 的两种情况,答案一定包含 \(u\)。
这样的限制也是充分的。于是我们以 \(O(n\log n)\) 个限制完成了对 lca 的刻画。
对于查询,考虑扫描线。在对 \(R\) 扫描线的过程中,维护每种 lca 的 \(r\leq R\) 中,\(l\) 的最大值。这样这个 lca 可以被贡献当且仅当 \(L\leq l\)。使用树状数组维护。
但是要求的是 dep of lca 的个数。所以把 dep 相同的合一起计算。
复杂度 \(O(n\log^2 n+q\log n)\)。
P8528 $^?$
看题解了吗?如看。没看吧。又好像看了。。?
同样找到 \(O(n\log n)\) 个支配对。然后每个支配对可以看做是 ban 了一些 \(L\in[x,y],R\in[u,v]\)。
放在平面上 ,就是 ban 矩形,然后求一个矩形内,在 \(y\geq x\) 里没有被 ban 的面积。
使用历史和线段树求解。
P11364 $^!$
一年过去了,但是我还是不会 NOIp 2024 T4。。。
考虑 \(\max dep(LCA^*)\) 可以这样转化:\(LCA^*(l,r)=\min_{i\in[l,r)}a_i\)。其中 \(a_i=dep(\text{lca}(i,i+1))\)。
于是问题变成 \(\max_{i\in[l,r-k+1]}\min_{j\in[i,i+k)}a_j\)。
区间最值考虑笛卡尔树。 我们发现,对于 \([l,r]\),其区间最值就是 \(lca(l,r)\)。
对于区间最值,同样的,在一个区间 \(A\) 外侧包含其的区间 \(B\),一定有 \(B\) 支配 \(A\)。
所以根据这个思路,我们只要找到最值为某个值的极大区间,一共 \(\mathcal{O}(n)\) 个。
然后对于这些区间,会贡献到询问区间 \(q\),当且仅当包含了极值,且交集长度 \(\geq k\)。
太麻烦了。注意到有支配这个性质在,所以我们不需要管极值,因为真正的答案区间一定是包含了极值的。
只要判断 \([L,R]\) 和询问区间 \([l,r]\) 的交即可。
有:\(R-L+1\geq k,L\leq r-k+1,R\geq l+k-1\)。
直接做三维偏序 \(2\log\)。已经可以通过。
然后考虑优化。发现 \(R-L+1\geq k,R\geq l+k-1\),这两个通过分类讨论可以去掉一个:
- \(R\geq r\),此时 \(L\leq r-k+1,R\geq r\)。
- \(R<r\),此时 \(l\leq L\leq r-k+1,R-L+1\geq k\)。
对于第一个直接扫描线。
对于第二个,因为要维护的信息不太能撤销。我们要换维对 \(R-L+1\) 扫描线。。
复杂度 \(\mathcal{O}(n\log n)\)。
type II
本质不同的仍然有 \(\mathcal{O}(n^2)\) 种,但是因为问题是求 \(\min/\max\),所以仍然找到 \(\~\mathcal{O}(n)\) 种支配对。
CF765F
接下来默认提到的区间,都满足区间的答案都是端点的差。否则这个区间显然不是支配点对。
考虑对于任意一个 \([l,r]\)(不妨假设 \(a_r\geq a_l\)),我们发现,以 \(l\) 为左端点,\(r'>r\) 的 \([l,r']\) 成为支配点对,要满足,\(a_{r'}-a_l\geq 2(a_r-a_l)\)。
否则会被 \([r,r']\) 偏序。
于是固定 \(l\),满足 \(a_r\geq a_l\) 的支配对只有 \(\mathcal{O}(\log A)\) 种。\(a_r<a_l\) 同理。
复杂度 \(O(n\log^2 A)\)。
codechef MINXORSEG
类似题目。
考虑 \(a_l,a_r\) 二进制下的 lcp。显然 lcp 只有 \(\mathcal{O}(\log A)\) 种。
我们发现,对于 lcp 相同的,只要 \(r\) 最小的。否则被 \([l,r]\) 偏序。
然后做法其实差不多。
P9058 $^?$
树上路径问题,考虑点分治。
然后问题就变成如何找到当前分治中心为根的支配对。
考虑第 \(i\) 个点的深度 \(a_i\)。
考虑区间 \([i,j]\) 如果是支配对,那么要满足 \(\forall k\in(i,j),\min(a_i,a_j)+a_k>a_i+a_j\)。
注意到,这种情况下,可以找到的支配对是不漏的。所以不必去管 \(i,j,k\) 是否有在同一颗子树之类的情况。
所以 \(a_k>\max(a_i,a_j)\)。也就是 \(\min_{k\in(i,j)}a_k>\max(a_i,a_j)\)。
在纸上画一画,我们发现,只有 \(l\) 是 \(r\) 前第一个 \(\leq a_r\) 或者 \(r\) 是 \(l\) 后第一个 \(\geq a_l\) 的时候才有可能是支配对。而这种的数量已经是 \(\mathcal{O}(n\log n)\) 可以接受了。
然后此时随便做到 \(\mathcal{O}(n\log^2 n)\)。
杂题
杂题
CF2153 F
简单题。
考虑离线可以莫队。那在线就可以分块。
我们每 \(\sqrt n\) 个一个块,记录块 \([l,r]\) 间的答案。然后暴力拓展左右两侧的散块。
这里暴力拓展要先知道当前 \(a_i\) 出现了多少次。我们在块 \(x\) 右端点处记录一个 \(f(x,v)\) 表示 \([1,x]\) 出现了多少个 \(v\)(只记录奇偶)
然后查询的时候只要差分一下,然后同时记录散块里值的出现次数。复杂度 \(O((n+q)^1.5)\)。
CF1781 F $^?$
比较不会这种。
不考虑按照括号匹配顺序去 dp。而是注意到,操作区间只有包含和不交,按照操作顺序的括号顺序 dp。
也就是注意到加入的是 \(()\) 或 \()(\),把同一次加入的看做一对“括号”就可以按照括号顺序 dp 了。
因为要维护括号序列的合法性,所以维护 \(f(i,k)\) 表示当前 dp 区间长度为 \(i\),前缀右括号比左括号最多多多少。每次类似括号匹配 dp 的转移,枚举是拼接两侧的区间,或者是在外面套一层括号。
稍微优化一下做到 \(O(n^3)\)。
P4696
一种显而易见的做法是使用线段树滑动窗口维护 \(a[l,r]\) 之间的数的 \((i-l)\times b^{rk_i}\) 这个哈希。
还有一种想法是,这样匹配的问题,能不能 KMP。
KMP 解决模式串匹配,要解决的是,怎么表示两个位置匹配。
我们考虑获得一个位置 \(i\) 在模式串 \(s[1,i]\) 的前驱后继的位置 \(i-x,i-y\)。如果文本串 \(t\) 的位置 \(j\) 有 \(t_{j-x}<t_j<t_{j-y}\),那么我们说 \(s_i,t_j\) 是匹配的。
因为我们发现,如果每个 \(j\) 都匹配,我们可以唯一确定匹配串每个位置的排名。所以直接 KMP。
复杂度线性。
CF1928F
曾经根本不敢订正的题,现在也是一眼了。。真实难度应该 *2600。
先给出转化后的题目。
考虑本质上是对序列 \(x,y\) 插入删除,然后动态维护 \(\sum_i\sum_j f(i,j)\)。其中 \(f(i,j)=\sum_{k=1}^i(i-k+1)(j-k+1)\quad (i<j)\)。
这种东西直接拆贡献。
得到 \(f(x,y)=\frac{x(x+1)(2x+1)}{6}-\frac{x^2(x+1)}{2}+y\frac{(x^2)+x}{2}\)。
注意到要保证 \(f(x,y)\) 的 \(x<y\),所以启发我们思考线段树维护。因为在合并信息的过程中左右两个区间天然地满足这个要求。
于是我们以 \(x_i,y_i\) 为下标建线段树。一个节点分别维护 \(x,y\) 的信息。
然后合并两个区间的时候,维护 \(x,y\) 的 \(\sum A,\sum B,ans,cnt,\sum y(或x)_i\)。
然后 \(cnt\) 就是其中 \(x_i(y_i)\) 的个数。
两个区间的信息合并是简单的。
然后回到题目,要求相邻不相同,其实就是限制,正方形边界不可以跨过 \(a_{i+1}=a_i\) 或 \(b_{i+1}=b_i\) 的位置 \(i\)。
区间加减本质上是对差分单点修改。然后用 set 维护连续段。做完了。
复杂度 \(O(n\log n)\)。

浙公网安备 33010602011771号