2025年2月杂题集

2025年2月杂题集

目录


Part 1

P5904 [POI 2014] HOT-Hotels 加强版

长链剖分与 DP 练习题。首先推出 O(n2) 的 DP 式子,由于第二维都与深度有关,所以可以使用长链剖分优化成 O(n)

对于长链上的儿子直接用指针继承状态,注意要精细实现才能不发生内存混乱。而对于非长链上的儿子则暴力合并。有点类似启发式合并的感觉。

有一些转移式子是枚举两个儿子,需要开一个临时数组记录前缀和优化复杂度。


P10085 [GDKOI2024 提高组] 染色

染一次是这样:

.o.
ooo
.o.

如果再把周围四个方向都染上就会变成:

..o..
.....
o.o.o
.....
..o..

我们把它称作 1 长十字架。

以此类推,每 52x 长十字架可以组成一个 2x+1 长十字架。

注意到如果我们放一个 2n1 长十字架,那么左右的就会重合,上下的就会重合,于是就实现了染一个点。

于是我们依次缩小十字架的长度,最后就能知道哪些点染的是 0 长十字架。复杂度 O(22nn)


P1935 [国家集训队] 圈地计划

类比文理分科。变成最小割模型,割完后与 S 相连则选 A,与 T 相连则选 B

注意到这道题是相邻不同有额外贡献,而不是相同,那么我们可以先黑白染色,黑点是左 AB,白点是左 BA
此时额外贡献就很好表示了,还是从 S 向新增点连一条容量为 C 的边,从新增点向相邻两个点连容量为 inf 的边,另一边也同理。
最后答案就是总和减去最小割。


[ARC107F] Sum of Abs

还是最小割模型,不过建模需要仔细斟酌。

最理想情况下,答案应该是 (bi<0bi)+bi0bi=|bi|,而实际上很难达到理想状态,所以我们可以从理想状态调整建模:

  • 删掉这个点,使答案减少 ai+|bi|
  • 一个 bi<0 的点放入取正的连通块,使答案减少 2bi
  • 一个 bi0 的点放入取负的连通块,使答案减少 2bi

所以把一个点拆成两个点 ini,outi,左右连 ST,中间连上删点的贡献。

我们还有一个连通块内正负性相同的限制,所以如果 (u,v),那么 outuinv,outvinu


P9878 [EC Final 2021] Check Pattern is Bad

构造题。

Part 1 判断原图是否已经不合法。

Part 2 首先把能确定的都确定了,即把形如

WB
B?

这样的可以直接将问号换成 B

我们正反扫两次就能把这些填完。过程中如果出现填两个颜色都不合法的格子也要输出 NO

Part 3 每次对于剩下的问号,随机填,每填一个就从它开始搜索把能确定的都确定了。注意可能不合法需要回溯,因此要记录搜索时填了哪些位置。


Part 2

CF888G Xor-MST

看到异或首先想到 01-Trie。考虑 Kruscal 的过程,每次找到一条最小的边,看是否能连上。

发现在 01-Trie 上,两点的异或和主要与它们的 LCA 深度有关。

因此我们可以联想到,n 个点的 01-Trie 恰好有 n1 处分叉,即拥有两个儿子的节点。而这些分叉就是答案 MST 的边的端点的 LCA。

现在我们只要对每一个分叉,求出在左右子树中各选一个点,求最小的异或和,可以枚举 Size 较小的一个子树,然后在另一个子树内查询。根据启发式合并的思想,这样枚举是均摊 log 级别的,而查询也是 log 级别的因此最终复杂度是 O(nlognlogV)

我们可以事先对 a 数组排序,然后在全局的 Trie 上做这些过程,这样就省去了启发式合并 Trie 的过程。


P4098 [HEOI2013] ALO

枚举一个 i,考虑当 ai 为次大值时,求异或的最大和。

可以用 ST 表加二分求出前驱最大值和后继最大值,然后我们需要区间查询异或和的最大值,用可持久化 Trie 即可。

时间复杂度 O(n(logn+logV))


P4585 [FJOI2015] 火星商店问题

写起来感觉有一点 shi 的数据结构题。

首先有一个线段树套可持久化 Trie 的做法,对商店开线段树,对时间可持久化,这样时间和空间都是 O(nlog2n),很不优美。

有一个使用线段树分治可以做到时间 O(nlog2n),空间 O(nlogn) 的做法。

我们把询问的时间区间插到线段树上,于是一件物品就是单点插入,可以用 vector 按商店编号排序,自顶向下更新询问。

01-Trie 则显然就是按商店编号可持久化了。这样做每到一个节点会开一个 Trie,而用完就删掉了,因此空间可以少一个 log


[AGC023F] 01 on Tree

被称作 Exchange Argument(临项交换)技巧的贪心题。

这道题和之前 abc 的某道 G 题很像。

考虑自顶向下删点很难做,我们可以从独立的 n 个点开始,每次选择一个点,令它与其父亲连边,表示它的父亲删完以后,立刻删掉它所在的连通块。而每当与 0 号点(1 的父亲)连通时就代表执行删除连通块的操作。

而我们需要确定一个连边的顺序,这里用了 Exchange Argument 的 Trick。如果连通块 a,ba0,b0v=0 的点,a1,b1v=1 的点,那么删 a 比删 b 更优当且仅当,a1×b0<b1×a0,即

a1a0<b1b0

于是将 a1a0 插入优先队列中即可。当 a0=0 时根据题意看作无穷大。

每次取出优先队列的 top,然后将其合并到它父亲的连通块,使用并查集维护连通块。

由于还要计算答案,需要在每个连通块维护一个 s 表示删除连通块内的点的贡献,合并时直接将 s 相加并且计算额外贡献即可。


P9678 [ICPC 2022 Jinan R] Tree Distance

双倍经验:P9058 [Ynoi2004] rpmtdq

以下 (i,j) 代表 dist(i,j)

我们把 (i,j) 看做点对 i,j 的权值,那么原题转化为了二维数点问题,直接做是 O((q+n2)logn)

瓶颈在于点对有 O(n2) 个,注意到很多点对是没有用的,实际上有用的点对很少,我们可以找出支配点对

如果点对 x,ya,b 满足 axyb(x,y)(a,b)a,b 显然是没有用的,我们称 a,bx,y 支配。
如果点对 x,y 不被任何另一对点支配,则 x,y 称作支配点对

我们可以找到一种支配点对的必要条件。将所有可能为支配点对的点对加入集合 S 并且要使 S 的大小可接受。

由于是与点对有关的信息,考虑点分治,设当前分治重心为 rt。我们把当前连通块内任意两点 x,y 的距离看做 (x,rt)+(y,rt) 即可,因为如果一个支配点对 LCA 不为 rt,则可以在其他分治重心被统计到。

先给出结论:对于 x<y<z(x,rt),(y,rt)(z,rt),点对 x,z 一定不是支配点对。x>y>z 也如此。在这里 x,zy,z 都在 rt 的不同子树内,否则可以在其他重心被统计到。证明如下:

(x,y)(x,rt)+(y,rt)(x,rt)+(z,rt)=(x,z)

所以 x,zx,y 支配。

因此只要对 x,将满足 y<x(y,rt)(x,rt) 的最大 y 与满足 y>x(y,rt)(x,rt) 的最小 yx 组成点对加入 S 即可。

可以将连通块内的点排序后使用单调栈维护。

这样连通块内的每个点都有 O(1) 个点对,而点分治均摊有 O(nlogn) 个点,就有 O(nlogn) 个点对。

剩下的就很简单了,离线后对 l 扫描线,用树状数组维护 r 的前缀最小值做二维数点。

时间复杂度 O(nlog2n+qlogn)


Part 3

P4757 [CERC2014] Parades

模拟赛场切的一道题。

由于贪心不可做,所以考虑 DP,首先想设 fx 表示子树 x 内最多选多少条路径。

那么考虑把路径挂在 LCA 上选,对于当前点 x,对于一条路径 (u,v) 满足 LCA(u,v)=x,选这条路径的贡献就是 fu+fv+1 再加上这条路径上挂着的那些子树的贡献。

除此之外选路径 (u,v) 还要满足 x 的在 uv 方向上的边没有选,于是我们改进状态,加入状态压缩,设 fx,S 表示选了儿子集合 S 的答案。

我们可以先用这些路径初始化 f,然后再 O(310) 枚举子集合并 f

最后的问题如何算路径的贡献,有了状态压缩的 f 后就很容易做这个问题,对于 x,fax,我们只要把 ffax,Ux 加到 x 的子树中即可,其中 U 表示全集。

可以使用树状数组运用差分做子树加、单点查。

时间复杂度 O(310n+(m+n)logn)


P5065 [Ynoi2014] 不归之人与望眼欲穿的人们

模拟赛没做出来的一道分块好题。

首先有一个性质:固定区间左端点后,不同的右端点最多有 O(logV) 个不同的或值,其中 V 是值域。

那么据此可以写出一个 O(qnlogV) 的做法并得到 70pts。

我们现在要处理出一个数组 bi 表示区间长度小于等于 i 时按位或的最大值是多少。这样查询时即可直接二分。

由于只有 O(nlogV) 个不同的或值,所以考虑把区间的左端点往右移的过程中,维护出每个不同的或值及其位置。

可以用链表实现,当插入左端点 l 时,将所有位置或上 al,将 l 作为链表的头,然后对于相同的或值只保留最前面的一个。

每次修改都这样暴力重构。

考虑改进这个做法,瓶颈在于修改时所有位置都扫了一遍太浪费了。考虑分块,设块长为 B

那么合法的区间分为在一个块中和跨越多个块的情况。

在一个块中

修改时用上面的做法暴力重构一个块,查询时枚举每个块接着做二分,复杂度 O(qBlogV)

跨越多个块

还是运用上面的性质,一个块内的前缀或后缀只有 O(logV) 个不同的或值,那么总共有 O(nBlogV) 个不同的或值。考虑这样做:

posi 为所在块的编号,lx,rx 为块的左右端点。我们把一个区间 [L,R] 拆成 [L,lposR1][lposR,R] 分别贡献。

那么我们可以枚举块 x,用以 lx1 结尾的后缀与 lx 开头的前缀合并在一起做贡献,由于前者与后者都有最多 O(logV) 个或值且都单调,所以可以双指针做。这一部分是 O(qnBlogV)

后者可以每次暴力重构时处理出一个 prex 数组。

前者可以在从小往大枚举 x 的过程中,用类似上面的方法来做,每次加入一个块时,加入其中 O(logV) 后缀,可以在重构时处理出一个 sufx 数组,然后将之前所有值或上这个块的或和,然后将重复元素删去,一样用链表维护。这一部分是 O(qnBlogV)

而处理 prex,sufx 都是 O(qBlogV)

B=O(n) 时可以做到 O(qnlogV)


ARC192C - Range Sums 2

简单交互题,由于 p1<p2,我们问出 S=q(1,2) 后,对于 3in,分别问出 q(1,i),q(2,i)

如果 max(q(1,i),q(2,i))<Sp1<pi<p2,否则也可以知道在那一侧,然后根据大小关系就可以确定顺序。根据顺序就可以知道 a 数组。

p1+1=p2 时,可能需要多问一次 q(1,k)(pk=p11)q(2,k)(pk=p2+1) 来确定 ap1ap2


P5279 [ZJOI2019] 麻将

DP 套 DP 练习题,用时 2h10min。

首先我们先建一个能不能判定当前局面是否能胡的自动机,然后在自动机上 DP 即可。在此之前可以先写出判定的 DP 式子然后建自动机。

首先我们只需考虑每种牌的个数。我们先来判定五个面子的情况,设 fi,j,k,0/1 表示考虑完前 i 种牌后,当前预留了 j(i1,i)ki,有没有预留对子,值为当前最大的面子数。

注意到到 j3 时,可以把三张 i1 和三张 j1 分别组成两个面子,k3 时可以直接组成面子,所以 j,k<3

于是自动机上的每个点需要记录两个 3×3 的矩阵 f0,f1。另外我们不需要记录 i,因为自动机上并不关心考虑到哪种牌。

另外对于七个对子的情况,只需再在自动机上的每个点记录当前遇到的对子数 k

那么一个节点胡了当且仅当存在一个 f1 中的值大于等于 4,或者 k 大于等于 7

实现可以使用 map 里面套两个 3×3vector 和一个 int。注意初始化时只有 f0,0,0,k=0,其他设为 1。把所有胡的节点当做 0 号即可。

转移时枚举新增 x 张牌。有几种如下转移:

  1. f0 新增 x 张牌,转移到 f0
  2. f1 新增 x 张牌,转移到 f1
  3. f0 新增 (x2) 张牌,转移到 f1
  4. x2k k+1

转移时再枚举与 (i2,i1) 配成面子的张数、与 i1 配成 (i1,i) 的张数、留下 i 的张数,剩余的拼成尽可能多的面子。

注意 f0f1 中的值要对 4min 才能保证点数,且 1 不能参与转移。

发现算上初始点和胡节点只有 2092 个点。直接 DP 即可。

我们不要枚举排列,而枚举每种牌选的个数,通过阶乘算出排列的贡献,具体来说设 fi,j,k 表示考虑完第 i 种牌后,选了 j 个额外的牌,走到了自动机的 k 号节点的方案数。

那么设初始有 aii 号牌,则转移枚举 0p4ai,有

fi1,j,k×(4aip)fi,j+p,to(k,ai+p)

最后设 gi 为额外选了 i 张牌后还没有胡的方案数。答案为

1+i=1gii!(4n13i)!(4n13)!

可以理解为前者是第一张牌,后者是选了 i 张牌后再选一张的概率。

时间复杂度为 2092×4×n2


P4336 [SHOI2016] 黑暗前的幻想乡

容斥+矩阵树定理。

矩阵树定理(无向图)

矩阵树定理用于求一张图的生成树个数(生成树点数等于原图点数)。

定义邻接矩阵 AAi,j 表示 i,j 之间的边数,度数矩阵 DDi,i 表示 i 的度数,拉普拉斯矩阵 L=DA

则生成树个数为 det(L[n]{k},[n]{k}),即 L 除去任意一行与一列后的行列式。

行列式求值

定义如下,其中 p 为枚举全部排列,σ(p)p 的逆序对数。

det(A)=p(1)σ(p)Ai,pi

直接计算是 O(n!) 的,但我们可以消元计算做到 O(n3)

以下 a,b 表示两行。

  • 交换 a,b 行列式取反
  • aa×kk 为常数,行列式不变。
  • aa+k×bk 为常数,行列式不变。

那么我们可以将原矩阵高斯消元成仅 Ai,i 有值的矩阵,此时 det(A)=Ai,i

本题

由于同一种颜色的边不能重复选,所以可以考虑容斥,2n1 枚举每种颜色是否选,答案即为

S(1)n1|S|det

时间复杂度 2n1(n2)3,当 n=17 时约为 2×108


Part 4

P3317 [SDOI2014] 重建

如果直接套上矩阵树定理,这里度数矩阵即所有边权的和,发现 WA 了,为什么呢?我们考虑一下答案的构成:

答案应该是枚举所有树 T

TiETpiiET(1pi)

而矩阵树定理根据定义应该是所有可能树的边权乘积的和,即

TiETpi

那么后面那一坨东西怎么办呢?发现后面可以化成这样:

iET(1pi)=iE(1pi)iET(1pi)

代入得

iE(1pi)TiETpi1pi

由于我们用了除法,当 pi=1 时就爆炸了,所以当 pi=1 时,可以考虑 pipieps

时间复杂度 O(n3),比较的 eps 取了 1018pi=1eps 取了 1015


P4455 [CQOI2018] 社交网络

矩阵树定理(有向图)

邻接矩阵 Ai,j 表示从 i 连向 j 的边数,度数矩阵分为出度矩阵 Dout 和入度矩阵 Din 两种。

对于外向树(边从根连向叶子方向的树),k 为根的生成树个数为

L=DinA

ans=det(L[n]{k},[n]{k})

对于内向树(边从叶子连向根方向的树),k 为根的生成树个数为

L=DoutA

ans=det(L[n]{k},[n]{k})

本题

直接套用矩阵树定理即可,本题是以 1 为根的外向树。


P6097 【模板】子集卷积

题意是计算

Ci=jk=i,jk=0AjBk

前面 jk=i 就是 FWT 的或卷积,jk=0 等价于 |j|+|k|=|i|。可以考虑对每一种 popcnt 都开一个数组。

即设 Aia|i|,i,Bib|i|,i

那么我们可以计算

c|i|,i=j=0iajbij

其中 表示或卷积。

那么最后答案即 Ci=c|i|,i

在计算 c 时,我们计算一下复杂度,如果枚举 i,jO(n2n) 卷积则复杂度为 O(n32n) 无法通过。

但是 FWT 有一个性质,变换后的数组是可加的,即

FWT(A)=FWT(A)

所以计算出所有 ab 在没有经过逆变换时的和,然后再一起逆变换即可,复杂度为 O(n22n)


AT_arc100_c [ARC100E] Or Plus Max

SOS DP。

题意:对于每一个 i 计算。

maxjkiaj+ak

我们可以转而计算对于每个 i 子集的最大值和次大值,使用 SOS DP 记录最大值和次大值即可。

时间复杂度 O(n2n)


AT_abc212_h [ABC212H] Nim Counting

FWT 的可加性、等比数列求和。

算法 1n 次 FWT 卷积,时间复杂度 O(nKlogK)

算法 2 由于 FWT 的可加性,我们可以只做一次 FWT 卷积,我们现在就是要对每一项求 a+a2+a3++an

使用矩阵快速幂写出以下式子可以做到 O(KlogK+Klogn)

[110a][Sak]=[S+akak+1]

事实上 a+a2+a3++an 是等比数列,使用等比数列求和公式:

a 为首项,r 为公比,n 为项数,其中 A1=a,Ai+1Ai=r

  • r1 时。

    i=1nAi=a×rn1r1

  • r=1 时。

    i=1nAi=a×n

时间复杂度 O(KlogK+Klogn)


Part 5

jzoj 7366 可怜的木偶 (dance)

由于 k![1,k] 所有数的倍数,所以可以先走到 0。然后要走到最小正整数。

给出结论,如果确定了 a 数组,则最后最小走到 gcdi=1nai。证明:

  • 证明答案不小于 gcd:因为所有数都是 gcd 的倍数,且初始时 k! 也是 gcd 的倍数,所以不能走到不为 gcd 倍数的位置,则不能小于 gcd
  • 证明可以达到 gcd:考虑前 i1 个数的 gcdd,现在加入第 i 个数 ai,根据裴蜀定理 dx+aiy=gcd(d,ai) 一定有整数解,即可以通过走若干次 dai 走到 gcd(d,ai),因此 n 个数可以走到 gcdi=1nai

考虑设 f(x) 表示 gcdx 的方案数。设 g(x) 为所有 gcdx 的倍数的方案数的总和,则

g(x)=kxn=x|df(d)

根据莫比乌斯反演,

f(x)=x|dμ(d)×g(dx)

最后的答案即为

i=1ki×f(i)kn

根据实现可以做到 O(Tklogk)O(klogn+Tk),足以通过此题。

更优的复杂度

展开得

x=1kxx|dμ(dx)×kdn

枚举 y=dx

x=1kxy=1kxμ(y)×kxyn

枚举 xy

i=1kj|ij×μ(ij)×kin

根据狄利克雷卷积 j|ij×μ(ij)=φ(i)。因此答案为

i=1kkinφ(i)kn

套上数论分块可以做到 O(klogn+Tk)


SP11470 TTM - To the moon

区间加的可持久化线段树。

调了很久终于发现了问题所在:由于用了标记永久化,标记不下传,因此不能从两个子树合并贡献,需要在修改下传时在每个节点加上贡献。

void update(int &x,int y,int l,int r,int L,int R,int z){
if(!x) x=++tot,ls[x]=ls[y],rs[x]=rs[y],tag[x]=tag[y],s[x]=s[y];
s[x]+=(ll)(min(R,r)-max(L,l)+1)*z;
if(L<=l&&r<=R) {
tag[x]+=z;
return;
}
if(L<=mid) {
if(ls[x]==ls[y]) ls[x]=0;
update(ls[x],ls[y],l,mid,L,R,z);
}
if(R>mid) {
if(rs[x]==rs[y]) rs[x]=0;
update(rs[x],rs[y],mid+1,r,L,R,z);
}
}

其中第三行 s[x]+=(ll)(min(R,r)-max(L,l)+1)*z; 很重要,并且最后不应该 s[x]=s[ls[x]]+s[rs[x]]


AtCoder WTF2019 A

考虑到每次把 1n 扫一次 K 就会减 1,每次 K1 我们称作一轮。

我们应该要做 K+1 轮就必定能找到宝藏。

考虑到 1n 扫完后,最后一个开的盒子 x 一定没有宝藏,于是下一轮就可以不用扫 x

也就是对于除了第一轮的每一轮,我们可以选择一个盒子不用开,因为这个盒子在上一轮的最后开过了。

那么令 b 为上一轮最后开的盒子,找到 nx 为满足与 b 不等且使 anx 最小的位置,那么扫一遍所有满足 inxib 的盒子,最后再开 nx,然后 bnx

每次开一个盒子时让 aiai1

当存在 ai<0 时无解,否则一共开了 n(K+1)K 次盒子。时间复杂度 O(nK)


AT_awtf2024_d Almost Bubble Sort

相当于选一个下标集合 S,使得 S 内元素 +n,然后统计逆序对个数。

发现它又等于 inv({1n}S)+inv(S)+(iSni)(|S|2)。其中 inv(S) 表示子序列 S 的逆序对个数。即 S 的逆序对个数加上除去 S 的逆序对个数再加上对一个 01 排序的交换次数。

如果考虑把 n 个点表示成平面上的 (i,pi),那么发现最优选 S 的方案一定形如有一条从左下角开始的向右向上的折线,使得折线下方都 +n

由于最后有一个关于 |S| 的贡献,所以如果直接 DP 并不好做。考虑设 c1i 表示 i 左上方的点数,c2i 表示 i 右下方的点数,那么选 S 就会贡献 c2i+ni,并且最后的最后要加上 (|S|2),而不选 S 就会贡献 c1i

我们可以初始让所有点都不选 S,然后每次选一个点让它 +n,那么选一个点的贡献为 fi=c2ic1i+ni。那么对 f 排序后按顺序选即可,这种方式也能方便贡献 (|S|2),时间复杂度 O(nlogn)


P7771 【模板】欧拉路径

欧拉路径:一个图中经过每条边恰好一次的路径,允许经过重复点。

欧拉回路:起点与终点相同的欧拉路径。

对于连通图,欧拉路径有如下判定:

  1. 对于无向图,恰好有两个点度数为奇数时,存在起点与终点不同的欧拉路径,且起点与终点就是这两个奇度数的点。
  2. 对于无向图,所有点度数均为偶数时,存在欧拉回路。
  3. 对于有向图,存在一个点 x 满足 degout+1=degin,且存在一个点 y 满足 degin+1=degout,且其他点入度等于出度,则存在起点与终点不同的欧拉路径,且 x 是起点,y 是终点。
  4. 对于有向图,所有点入度等于出度,存在欧拉回路。

寻找欧拉路径

基本思想:定义递归函数 dfs(x) 返回一个 x 的环,过程如下,先找到一个 x 的环 T 使得每条边都没有被走过,然后对于环上的每一个点 y,将 dfs(y) 返回的环插入 T 中。

算法实际上不太一样,对于 dfs(x)

  1. 首先遍历每条未走过的出边(可能之前调用过 x 导致一些出边已走过)到 v
  2. 调用 dfs(v)
  3. 当所有出边都遍历完后,将 x 加入答案序列。

最后倒序输出答案序列即题目所需的答案。

本题还要求字典序最小,因此需要将出边排序,用 vector 记录出边。

实现上对于每一个点 x 记录 curx 表示当前弧,因为一个递归树中可能出现标号为 x 的点的子树内又出现了标号为 x 的点。


Part 6

P6628 [省选联考 2020 B 卷] 丁香之路

考虑题目要求的路径就是从 s 开始 i 结束的欧拉路径。我们先插入一条边 (s,i) 把题目变成欧拉回路。

那么接下来就是要用最少的边权使原图变为合法的欧拉回路。

我们从 1n 遍历 i,如果 i 的度数为奇数,则连一条 (i,i+1),发现这样连边是最优的,比把相邻度数为奇数的点相连更优,因为这样连边还可以使得图尽可能连通。

但图还有可能不连通,考虑把有边的点对用并查集缩点,相邻的点之间建边,然后跑最小生成树,发现欧拉回路的答案就会加上两倍最小生成树的权值。

时间复杂度 O(m+n2+nlogn)。给定的 m 条边要预处理,因为如果每个 i 都枚举这 m 条边,复杂度将变成 O(nm+nlogn)


AT_agc018_f [AGC018F] Two Trees

很厉害的结论题。

由于 11 的奇偶性相同,如果一个编号在左树和右树中儿子个数的奇偶性不同就是无解。

否则我们可以这样构造:
先将两棵树的根连向一个超级根,那么现在所有节点都等价了。
对于度数为奇数的点,我们将它们在两棵树上的点连起来。
那么现在所有点都是偶数度数,我们跑出欧拉回路。
对于原本是偶数度数的点,X=0
对于原本是奇数度数的点,如果额外的那一条边在回路上是从左走到右,那么 X=1,否则 X=1

证明:对于树上一个点,欧拉路径进出其子树偶数次,其中一次经过其与其父亲的连边,剩余奇数次进出其子树内的额外边,且进入和出去的次数恰好相差 1,那么因为进出的边权为 ±1,所以这个点的子树和就是 ±1


ARC193B Broken Wheel

因为 d 是一定的,所以确定了 (d0,d1,dn1) 就能确定 dn,所以考虑计算它。

显然一种 d 序列可能对应多种连边方式。我们可以设 fi,0/1/2 分别表示 (i1,i) 一定选连右、一定选连左、连左右均可的 (d0,d1,,di1) 方案数,这里的「连左右均可」计算的是满足连左或连右都可以被构造出的 (d0,d1,,di1)

我们根据 si1 的值讨论每一种可能的 di1 即可转移。

那么我们指定 (n1,0) 连的是什么边,对应以下初始化与需要加上的值:

  • f0,0=1,f0,1=f0,2=0,计算 fn,0
  • f0,1=1,f0,0=f0,2=0,计算 fn,1
  • f0,2=1,f0,0=f0,1=0,计算 fn,2

以上,发现会算重的情况当且仅当 (d0,d1,,dn1)=(1,1,,1),且 (n1,0)0/1/2 都会被算一次。

所以最后将答案减 2 输出即可。


P8528 [Ynoi2003] 铃原露露

考虑对于 (x,y,z=lca(x,y)),如果 ax<az<ay 那么不会对不合法区间造成贡献,否则:

  • az<ax<ay,则对于 l(az,ax],ray 的区间不合法。
  • ax<ay<az,则对于 lax,r[ay,az) 的区间不合法。

可以想到一个树上启发式合并的过程,维护每个点子树内 a 集合,当 x,yz 处合并时,插入不合法的区间。

由于不合法的区间是包含 x,y 而不包含 z,所以当 x 合并到 S 集合中时,只要查找 axS 中的前驱与后继即可。

每次合并一个节点产生 O(1) 个支配对,所以支配点对的数量是 O(nlogn)

接下来的问题形如给一个矩形加,然后查询矩形内为 0 的位置个数。

扫描线以后,就是区间加,差分后查询区间为 0 的个数的历史和。使用线段树维护。

具体来说,我们维护维护区间最小值、最小值的个数、0 的个数的历史和。

标记需要维护加标记、历史标记。历史标记表示区间内最小值会对历史和贡献多少次。

下传历史标记时需要知道哪些子区间是原先的最小值,因此上传时需要记录区间最值由哪些子区间转移而来。

每次如果全局的最小值为 0,则对树根的历史标记加 1

时间复杂度 O(nlog2n+qlogn)


P9166 [省选联考 2023] 火车站

对于一条轨道 l,r,我们 i[l,r) 连无向边 (i,i+1)。则只需统计与 x 连通的点即可。

由于轨道之间是没有区别的,所以可以差分实现区间加 1,当 si>0 时表示 (i,i+1) 之间有一条边。

查询则从 x 开始往左和往右走,往左只统计左端点,往右只统计右端点。时间复杂度 O(n)


Part 7

P2391 白雪皑皑

由于后来的区间会覆盖之前的区间,我们考虑倒着做,那么每次就要覆盖区间内的 0

考虑并查集维护一个点后继的 0,时间复杂度 O(nα(n))

posted @   dengchengyu  阅读(16)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示