杂题集1

\(1 \sim 20\) 道杂题。

完结于 \(2025.3.3\)

众数

你有 \(n\) 个数对 \((a_1,b_1),\ldots,(a_n,b_n)\)

定义下标 \(i(1\le i\le n)\) 的权值为将 \(a_1\)\(b_1\)\(a_2\)\(b_2\),...,\(a_i\)\(b_i\) 拼接在一起后形成的数组的最大众数(特别地,若所有数出现次数相同则为最大数)乘以 \(a_i\)

接下来你有 \(m\) 个操作,分两种:

  • 1 x y,将 \(a_x\) 增加 \(y\)保证 \(y\) 非负。
  • 2 q,求最小的正整数 \(k\) 使得下标 \(n-k+1 \sim n\) 的权值异或和为 \(q\)

2 操作保证有解,且所有答案之和(记为 \(\sum k\))不超过 \(5\times 10^7\)


发现 \(\sum k \le 5 \times 10^7\) 且一定有解,显然考虑从后向前枚举,此时就要求我们用 \(O(1)\) 的复杂度求出前缀众数,那么复杂度就要摊到修改上。

发现没办法用一些神仙数据结构直接维护,考虑分块,由于每一个点会对其后的所有点造成贡献,所以维护每一个块的结尾的前面所有对其产生了贡献的修改(包括输入),但此时复杂度会达到 \(n \sqrt{n}\)

此时有一个非常优秀的思路,从后往前建大小为 \(1,2,4 \cdots\) 的块,此时总块数为 \(\log n\),从后向前枚举的复杂度可以依然保持 \(O(n)\)

[ARC107F] Sum of Abs

\(N\) 个点 \(M\) 条边的无向图,每个点有两个权值 \(A_i\)\(B_i\)。可以用 \(A_i\) 的代价删除第 \(i\) 个节点。并删除与这个点相连的边。一个极大连通块的权值定义为 \(B_i\) 的权值和的绝对值。

删除一些节点后,收益定义为所有极大连通块权值之和减去代价和。求最大的可能收益。


最小割神题。

每个点只有可能有三种情况:正贡献,负贡献,删除。

最小割。

\(\sum{|b_i|}\) 上减。

有连边的点一定贡献的正负相同,所以连inf。

拆点来处理删除操作。

[SCOI2011] 植物大战僵尸

坚果保龄球游戏,从每一行的起始开始滚,前 \(N/2\) 排撞到僵尸向右下滚,后 \(N/2\) 排撞到僵尸向右上滚,之后撞到僵尸僵尸死,坚果变向,有 \(k\) 轮,依次输出每轮最多撞死多少僵尸。


苟题。

至今仍然不知道这跟网络流有个毛线关系。

容易发现所有轨迹都是链。

用平衡树维护每一个链,存储每一行开始的杀死僵尸数量。

记住,更新答案的时候每一个链的开头有可能不能到达,所以是从能到达的最靠前的点开始。

「CF gym102759C」Economic One-way Roads

将无向图变为有向,每条边都必须要变。给你变化后正反边的权值,求变为强连通图的最小代价,或判无解。


主要是记录一个小trick。

u->v和v->u两条边权值不同,必须选一个,这就导致了跑完耳分解之后有一些不必要的边没有统计。此时可以将 \(A_{u,v}\)\(A_{v,u}\) 同时减去 \(\min(A_{u,v},A_{v,u})\) ,这样就可以保证在必须选择一条边的情况下边权总和最小了。

[NOI2021] 密码箱

\(a_0 = 0, a_1 = 1\)

  • W 类型:给数列的最后一项\(1\)
  • E 类型:若数列的最后一项\(1\),则给倒数第二项加 \(1\);否则先给数列的最后一项\(1\),接着在数列尾再加两项,两项的值都是 \(1\)

\[f(a_0, \ldots , a_{k - 1}, a_k) = \begin{cases} a_0, & k = 0 \\ f \! \left( a_0, a_1, \ldots , a_{k - 2}, a_{k - 1} + \frac{1}{a_k} \right) \! , & k \ge 1 \end{cases} \]

  • APPEND c,追加操作,其中 c 为字符 WE
  • FLIP l r,反转操作。
  • REVERSE l r,翻转操作。

每次修改后询问 \(f\)


平衡树+矩阵乘法好题。

发现两个数进行合并可以看作:\(\frac{1}{a_i+\frac{a}{b}}\)。其中 \(\frac{a}{b}\) 是操作从后向前进行的当前值。

发现可以矩阵乘法维护:

\[\left[ \begin{matrix} a^{'} \\ b^{'} \\ \end{matrix} \right] = \left[ \begin{matrix} 0&1 \\ 1&a_i \\ \end{matrix} \right] \left[ \begin{matrix} a \\ b \\ \end{matrix} \right] \]

W 操作的矩阵为 \(\left[\begin{matrix}1&1 \\0&1 \\\end{matrix}\right]\) ,E 操作的矩阵为 \(\left[\begin{matrix}0&-1 \\1&2 \\\end{matrix}\right]\)

然后尝试用平衡树进行维护。

这里有一个技巧。

要维护的信息是区间连乘积,区间取反连乘积,区间翻转连乘积,区间取反翻转连乘积,和两个 tag:是否取反,是否翻转。

然后直接糊。

简单树剖练习题

link

\(n\) 个点的无根树,常数 \(m\),树上编号为 \(i\) 的节点权值为 \(a_i\),设 \(x\)\(y\) 的边集为 \(E(x,y)\)。两种操作。

  1. \(x\)\(y\) 的最短路径上的点的权值增加 \(k\)
  2. 查询 \(\sum_{(u,v)\in E(x,y)}(a_u+a_v)|a_u-a_v|^m\)\(7667713\) 取模后的结果。

神仙zdj的题。优秀树剖题。

发现进行2操作之后 \(|a_u-a_v|\) 并不会发生改变。假设题目给定的是一条链,则每次改变 \(E(x,y)\) 的值为 \(2 k|a_u-a_v|^m\),可以用线段树进行维护,而两端的点连接的边直接暴力做就行了。

转换到树上,发现复杂度与经过的链的数量有关,容易想到重链剖分。

重链上的修改直接用线段树维护(这里维护的是边),经过的轻链的数量级同样是在 \(\log n\) 的,所以所有轻链在询问的时候直接暴力处理就行了,因此发现只需要维护重链。当然,还需要注意不在路径上但与路径上的边相邻的重链的修改。

轻链的维护方式是树状数组(这里维护的是点)。

完事儿。

Interactive Mex Tree

给你一棵树,并进行 \(q\) 次询问。

所有询问开始前,你可以构造两个 \(1∼n\) 排列 \(p_1,p_2\)

每次询问都生成一个 \(0∼n-1\) 排列 \(A\) 作为被隐藏的点权,并查询一条路径上的 mex。

每次询问你可以查询 \(5\)\(\min_{i\in[l,r]}A_{p_{x,i}}\) 的值。


死于读错英文题面。

主要的一个技巧是考虑入栈顺序和出栈顺序的特殊性质来表示所有链以外的点,求一下min其实就是链上节点的mex了。

「PA 2021」Fiolki 2

给定一个 \(n\) 个点 \(m\) 条边的 DAG,定义 \(f(l,r)\) 表示最多选取多少条不相交路径 \((s_i,t_i)\) 满足\(s_i\in[1,k],t_i\in[l,r]\),其中不能有任意一点同时在两条选出的路径上。对 \(∀x∈[0,k)\) 求出有多少 \([l,r]⊆(k,n]\) 使得 \(f(l,r)=x\)

\(n \le 105,m \le 106,k\le \min⁡(n−1,50)\)


非常好的线性代数,使我的大脑旋转。

随便口胡几句,怕自己之后忘完了。

转换一下题面,对于每个 \([l,r]\) 找到 \(f(l,r)\)

\(f(l,r)=x\),必须且最多要存在 \(x\) 条不相交路径。

发现DAG上不相交路径的带权值和可以使用LGV引理来解决。

然而这里可能会出现即使有满足条件的路径也会被乘上权值后和为 \(0\) 的情况。因此,运用Schwartz–Zippel引理,给每一条边赋一个 \([0,P-1]\) 的边权(P 可以取 \(1e9 + 7\))路径的权值为其上边权权值之积,这种情况下,无解的时候答案依旧为 \(0\),有解时极大概率不为 \(0\)

按照套路求出所有 \(e(x_i,y_i)\) 表示从 \(x_i\) 走到 \(y_i\) 的所有路径的权值和。

什么情况下答案会为 \(0\)?选择的列向量(确定 \(x_i\))线性相关时。

因此 \(f(l,r)\) 其实就是 \(r-l+1\) 个列向量构成的 \(k \times (r-l+1)\) 的矩阵的秩。

难点来了!如何确定每个区间的秩呢?

显然,如果暴力枚举每个区间时间复杂度会达到 \(O(n^2k^3)\)。显然不可能。

发现矩阵的秩最多只会是 \(k\),所以考虑枚举 \(r\),每次向前枚举 \(k\) 个数,复杂度为 \(O(nk^4)\)

每次高斯消元时可以不用从头再来,可以从当前状态开始,依次化简当前添加的向量,复杂度为 \(O(nk^3)\)

发现每次 \(r\) 左移一位本质上只会添加一个列向量。能否将复杂度优化到 \(O(nk^2)\) 呢?

当然可以。

贪心的想,\(r\) 确定时,作为矩阵的秩的几个列向量的下标自然是越大越好。所以可以在高斯消元时顺带进行替换。

不会讲了,直接放代码。

for (int i = 1; i <= k; i ++ ) if (c[ID][i]) {
    if (ID > id[i] || !id[i]) swap(id[i], ID);
    int t = c[ID][i] * q_pow(c[id[i]][i], mod - 2) % mod;
    for (int j = 1; j <= k; j ++ )
        c[ID][j] = (c[ID][j] - t * c[id[i]][j]) % mod;
}

此时,找到所有作为矩阵的秩的 \(id_i\),从大到小排序。类似差分,答案直接加上就行了。

「SDOI2014」重建

\(N\) 座城市,给定 \(A\) 数组,\(A_{i,j}\) 代表 \(i,j\) 间的道路存在的概率,求最后的图构成一棵树的概率。

\(N\le 50\)


\[\sum_{T}(\prod_{e \in T}p_e \prod_{e\notin T}(1-p_e))\\=\sum_{T}(\prod_{e \in T}p_e \frac{\prod_e(1-p_e)}{\prod_{e\in T}(1-p_e)})\\=\prod_e(1-p_e)\sum_{T}(\prod_{e \in T}\frac{p_e}{(1-p_e)}) \]

\(\sum_{T}(\prod_{e \in T}\frac{p_e}{(1-p_e)})\) 可以用矩阵树来做。

这里有一个小技巧,\(a_{i,j}\) 是有可能为 \(0/1\) 的,此时可以将其变为 \(eps/1-eps\),以便计算,这样做精度也不会出现问题。

「POJ3304」线段

在二维平面内有 \(n\) 条线段,请你编写一个程序,判断是否存在一条直线满足将这 \(n\) 条线段投影到该直线上后,所有的投影线段至少具有一个公共点。

\(1 \le n \le 100\)\(1 \le T \le 100\)


计算几何入门好题。

发现 \(n\) 条投影存在公共点的充要条件是有一条直线横穿所有线段。这条直线是和原题中的直线垂直的,垂足为公共点之一。

因此题目转换为判断是否有这样一条直线。

接着可以理解为将这条直线在可控范围内旋转,一定可以使得有一种合法情况下直线过原本线段的端点点集中的至少两个点。

\(O(n^3)\) 枚举。

[ZJOI2010] 贪吃的老鼠

\(m\) 只老鼠,\(n\) 块奶酪,第 \(i\) 块的大小为 \(p_i\),第 \(r_i\) 秒被生产,必须在第 \(d_i\) 秒之前吃掉。第 \(j\) 只老鼠吃奶酪的速度为 \(s_j\),要满足下面两个限制。

  • 在任一时刻,一只老鼠最多可以吃一块奶酪;

  • 在任一时刻,一块奶酪最多被一只老鼠吃。

所有的奶酪的 \(d_i\) 变成 \(d_i+T\),找到最小的 \(T\) 使得能吃完所有奶酪。

\(1 \le n,m \le 30\)\(1 \le p_i \le 10^5\)\(0 \le r_i<d_i \le 10^7\)\(1 \le s_j \le 10^5\)


神仙题目。

首先将整个时间离散化成时间段。

此时每个时间段中所有奶酪可食用时间是相等的。

一个很厉害的说法。

可以把每个时间段的老鼠的速度进行差分,先从小到大排序。

原速度序列的每个值都变成了:\(i\times (a[i]-a[i+1])\)

因此源点向每个奶酪连边 \(i\times (a[i]-a[i+1]) \times timec\)\(timec\) 是当前时间段的长度。

众所周知,每个奶酪可以像车轮战一样被老鼠换着吃。

结合小学二年级学的线性代数,每个奶酪被吃的部分可以表示为所有老鼠的速度的线性组合。

差分之后线性基是不变的!线性组合也是不变的!!!

所以改成差分之后不仅不会影响答案,还会顺手就限制了每一块奶酪不能同时被多只老鼠一起吃。

具体限制方法就是差分后的数组只向每一个奶酪连接 \((a[i]-a[i+1]) \times timec\) 的量就行。

发现这样更改后最大值与原问题相同,而时间可以被无线拆分,所以可以吃的量还是 \([0,\max]\)

所以直接跑最大流判断奶酪是否被吃完就行。

NOI2016 优秀的拆分

若一个字符串可以被拆分为 \(AABB\) 的形式,\(A,B\) 不为空,那么称 \(AABB\) 为该字符串的一种拆分方式。

求给定字符串所有子串的拆分方式之和。


有一个非常经典的 trick,令 \(a_i\) 为以第 \(i\) 个数为左端点的可以划分为相同的两段的子串的个数,\(b_i\) 为以第 \(i\) 个数为右端点的。

显然最后的答案为 \(\sum a_i\times b_i\)

这种方式加上 hash 可以达到 \(n^2\) 的复杂度并且获得 95 分。

考虑换一种方式以更高效的方法预处理出 \(a_i,b_i\)

发现如果钦定一个形如 \(AA\) 的串的长度为 \(x\),则每 \(\frac{x}{2}\) 个字符标记一下就可以确保这个子串必定经过两个标记的点。

对于相邻的两个点 \(u,v\)。将第 \(u\) 个前缀与第 \(v\) 个前缀的最长公共后缀记为 \(l\),第 \(u\) 个后缀与第 \(v\) 个后缀的最长公共前缀记为 \(r\),那么此时经过这两个点的长度为 \(x\) 的子串就一共有 \(l + r - 1 - i\) 个,使用差分就可以处理出 \(a,b\) 数组。

根据调和级数复杂度是 \(O(n\log n)\)

「2021 集训队互测」序列

有一个长度为 \(n\) 的序列 \(a_1,a_2,\dots,a_n\),序列里的每个元素都是 \([1,10^9]\) 内的正整数。

现在已知了 \(m\) 条信息,每条信息形如 \(i,j,k,x\),表示这个序列满足 \(a_i+a_j+a_k−\max(a_i,a_j,a_k)−\min(a_i,a_j,a_k)=x\)

请构造一个满足条件的序列。

\(1 \le n,m \le 10^5\)


非常好的一道题。

显然可以发现本题是给定了三个数中大小居中的数的值。

显然有一个性质:若 \(a_i \le x-1\)\(a_j,a_k \ge x\),若 \(a_i \ge x+1\)\(a_j,a_k \le x\)

当然这个性质中 \(i,j,k\) 可以调换。

发现 \(a_i \le x-1\)\(a_i \ge x\) 只能存在一个。\(a_i \ge x+1\)\(a_i \le x\) 只能存在一个。

然而这些所有的大小关系在以上性质中都存在。

考虑使用 2-SAT。

当然要注意对于同一个点如果有 \(a_i \le x,a_i \le y,x\le y\) 时,\(a_i \le x\) 要向 \(a_i \le y\) 连边,如果 \(x=y\) 则连双向边,限制不能漏,否则会误判为出现无解。

UOJ【UR #2】跳蚤公路

\(n\) 个点 \(m\) 条边有向图,有红、绿、白三种颜色的边,权值分别为 \(x,0,-x\)。要求对于所有 \(k \in [1,n]\),求出满足使得 \(1\)\(k\) 的路径上不存在负环的 \(x\) 的数量或指出 \(x\) 有无穷多种取法。

\(1\le n\le 100,1\le m\le 10000\)


这里要用到的是 Bellman-ford 判负环。

若图中存在负环,则一定存在一个 \(u\) 使得 \(dist_{u,n} < dist_{u,n-1}\)。在本题中只需要统计可以到达 \(k\)\(u\)

发现题目中 \(x\) 会变换,于是讲 \(x\) 也加入 dp。

\(dp_{u,i,j}\) 代表当前在点 \(u\) 经过了 \(i\) 条边,权值为 \(j \times x\) 的最短路。

那么就变为存在 \(\min dp_{u,n,j} < \min dp_{u,n-1,k}\)

此时可以发现将 \(x\) 代入可以变为解不等式。

再结合不等式解集的并交就可以求解出答案了。

[NOI2023] 贸易

给定一棵包含 \(2^{n−1}\) 个节点的完全二叉树,节点编号从 \(1\)\(2^{n−1}\)。树中每条边有一个权重,表示从一个节点到其父节点或子节点的贸易成本。此外,图中还存在额外 \(m\)条 边,连接祖先节点到其子树中的节点。

要求计算所有点对 \((u,v)\) 之间的最短路径之和,其中 \(u\)\(v\) 是树中的任意两个节点。

\(1 \le n \le 18,0\le m \le 2 \times 10^5\)


非常棒的一道题。

这种求路径长度和的题目一般可以通过考虑两点的 lca 来简化算法,本题也不例外。

对于 \(x \to y\) 这条路径,令其在树上的 lca 为 \(u\)

\(x \to u\) 一定是一直往上跳,否则一定更劣。

难点在于 \(u \to y\) 的过程。

\(dp_{i,j}\) 表示 \(j\) 的深度为 \(i\) 的祖先到 \(j\) 的最短路。那么每加一条祖先到子孙的边都可以更新所有在 \(j\)\(fa_i\) 之间的 \(A \to B\)

然后发现可以进行一个类似 Floyd 的转移,求出 \(dp\) 数组,最后统计答案就行。

2022CCPC广州 Math Exam

一个长度为 \(n\) 的整数序列 \(a_i\) 只有在满足以下所有条件时才是好的:

  • \(∀i∈[1,n],4S_i=a_i^2+2a_i+1\)
  • \(∀i∈[1,n],|a_i|≤m\)

其中 \(S_i=∑_{j=1}^ia_j\)

你将得到 \(n\)\(m\),并且保证 \(m\)奇数

找出有多少个序列是好的,对 \(998244353\) 取模计算。

\(1 \le n \le 10^7,1\le m \le 2n\)


非常好题目,使我大脑旋转。

推式子非常简单:

\[a_{i}^2-2a_{i}+1=a_{i-1}^2+2a_{i-1}+1\\ (a_i-1)^2=(a_{i-1}+1)^2; \]

得出 \(a_i=a_{i-1}+2\)\(-a_{i-1}\)

\(b_i=\lfloor\frac{|a_i+1|}{2}\rfloor-1\),发现每次变化 \(b_i\) 一定等于 \(b_{i-1}-1\)\(b_{i-1}+1\)

进行转换,从 \((0,0)\) 开始走,若是 \(-1\) 则向上,否则向右。

不能碰到 \(y=x+1\),因为当 \(a_i = -1\) 时只能转移到 \(1\)

不能碰到 \(y=x-\lfloor\frac{m+1}{2}\rfloor-1\),因为要满足 \(|a_i|\le m\)

此时问题就转换成了从 \((0,0)\) 开始走 \(n\) 步,不能碰到给定的两条直线的方案。

如果只是不能碰到一条直线是很好办的。用容斥将点对称过去再减掉就行了。

如果是两条直线,我们先考虑指定终点的情况。

走了 \(n\) 步,我们把每次经过 \(y=x+1\)\(y=x - (m + 1) / 2-1\),分别记作 \(A\),\(B\)。走 \(n\) 步后就可以得到一个 \(AB\) 序列。

将相邻的 \(A,B\) 缩在一起。

回到问题,我们尝试同样使用容斥来解决问题。发现答案可以转换为:所有情况-首先经过 \(A\) 的情况-首先经过 \(B\) 的情况。

首先经过 \(A\) 的情况怎么算呢?发现如果将终点延 \(A\) 对称,那么结果序列一定是以 \(A\)\(AB\) 结尾的。减去后发现有 \(BA\)\(BAB\) 的情况被多减了,此时再将对称后的终点延 \(B\) 对称,加上......

\(B\) 开头是同理的。

终点不定其实也不难,由于合法的终点一定是连续的,只需要考虑每次对称后左右端点是否合法,若不合法就变换就行了。

[AGC043D] Merge Triplets

  • 给定如下构造生成长度为 \(3N\) 的排列 \(P\) 的方法:
    • 先生成一个长度为 \(3N\) 的排列 \(A\)。然后将 \(∀k\in[0,N−1],A_{3k+1},A_{3k+2},A_{3k+3}\) 分成一块。
    • \(N\) 个指针,初始指向每个块的第一个数。
    • 每次选择所有指针指向的数中最小的数删除,然后放到 \(P\) 的末尾。之后指向被删除的数后移一个位置。若移出块了,则删除这个指针。
  • 请你求出,一共能生成长度为 \(3N\) 的排列共多少种。求出对 \(M\) 取模的结果。
  • \(1≤N≤2×10^3,10^8≤M≤10^9+7\)

有点意思。

容易发现,当生成序列中存在 \(a_i>a_{i+1}\),则 \(a_i,a_{i + 1}\) 一定在同一组。

按照前缀max对 \(A\) 序列进行划分,每一块都必需要在同一个三元块中。那么就一定满足:长度为 \(1\) 的块数量 大于等于 长度为 \(2\) 的块数量,且所有块的不超过 \(3\)

直接 dp 就可以了,当然这里有一个技巧,虽说是按照前缀max来算的,但是从最大值开始一个个往小了选显然更加方便,并且最终按照每一段第一个数排序后结果相同。

[AGC043B] 123 Triangle

给一个长度为 \(n\) 的由 \(123\) 组成的序列。

不断对这个序列做差分,求最后剩下的那个数。


蓝题,但是挺有意思的。

发现当序列中有 \(1\) ,最终的结果就一定不可能为 \(2\),因为 \(2\) 碰到 \(1\) 后必定会被消掉。

同理,没有 \(1\) 时答案一定不可能是 \(2\)

先考虑没有 \(1\) 的情况:

答案不是 \(2\) 等同于考虑答案的奇偶性,那么绝对值就可以直接变成加法,相当于是求:

\[\sum_{i=1}^Na_i\binom{N-1}{i-1} (\rm{mod}\ 2) \]

为什么呢?观察原式:

\[dp_{k,x}=dp_{k-1,x}+dp_{k-1,x+1} (\rm{mod}\ 2) \]

惊奇地发现这是组合数的倒推,没了。

然后没有 \(1\) 的情况直接给所有 \(2\) 都变成 \(1\) 最后答案乘 \(2\) 就行。

哦,顺带一提:\(\binom{n}{m}\ \rm{mod}\ 2=[n\ \rm{and}\ m = m]\)

收集

link.

给定 \(n\) 个点的图,\(n\) 条无向边构成基环图,还有 \(m\) 条有向边。求经过 \(m\) 条有向边且所有边至多经过一次的最短 回路 长度。

\(1 \le n \le 20000\)


假如选出了一些无向边,并且钦定了它们的方向,这时,为了形成一条欧拉回路,边集合法当且仅当

  • 边集是连通的;
  • 每个点的入度等于出度。

对于 \(m\) 条有向边,初始先让 \(d_i=\sum_{i\rightarrow v} 1 - \sum_{v \rightarrow i} 1\)(即出度减入度)。我们的目标是 \(d_i=0\)

考虑一棵树怎么做。注意到对于一片叶子 \(u\),与它关联的边只有一条 \((u,v)\),而这条边的不被选择 / 被选择且定向 \(u\rightarrow v\) / 被选择且定向 \(v\rightarrow u\) 三种操作对 \(d_u\) 的影响互不相同,于是这条边最终的状态可以确定(\(d_u\)\(0\) 则无解)。

一直按这样的方式缩叶子节点,成功缩完后检验是否连通即可。

对于基环树,枚举环上一条边的状态即可转化为树。

posted @ 2025-03-05 19:53  paper_zym  阅读(29)  评论(0)    收藏  举报