杂题

CF1097F Alex and a TV Show

niubi bitset 题。

维护 \(n\) 个初始为空的可重集,支持以下操作:

1 x v:令集合 \(x\) 等于 \(\{v\}\)

2 x y z:令集合 \(x\) 等于集合 \(y\)\(z\) 的并。

3 x y z:令集合 \(x\) 等于集合 \(y\)\(z\) 的积,\(A*B=\{\gcd(a,b)|a\in A,b\in B\}\)

4 x v:询问 \(v\) 在集合 \(x\) 中出现次数模 \(2\) 的结果。

\(1\leq n\leq 10^5,1\leq q\leq 10^6,1\leq v \leq 7000\)

注意到值域很小,又考虑需要维护 \(2\)\(4\) 操作,直接上 bitset,\(2\) 操作就变成了一个异或的过程。

考虑如何维护 \(3\) 操作。直接用目前的 bitset 是不好做的,考虑将 bitset 维护的东西变化一下。因为乘法涉及到一个 \(\gcd\),首先我们肯定考虑列出暴力的式子考虑能不能用各种反演搞定它。

\[\begin{aligned} S_u&=\sum_{i\in A}\sum_{j\in B}[\gcd(i,j)=u]\\ &=\sum_{iu\in A}\sum_{ju\in B}[\gcd(i,j)=1]\\ &=\sum_{iu\in A}\sum_{ju\in B}\sum_{d|i,d|j}\mu(d)\\ &=\sum_{d}\mu(d)\left(\sum_{iud\in A}1\right)\left(\sum_{jud\in B}1\right) \end{aligned} \]

后面两个东西形式相似,考虑把它们用一个函数代替。设 \(f(S,p)=\sum_{ip\in S}1\)。式子则变成:

\[S_u=\sum_d\mu(d)f(A,ud)f(B,ud) \]

显然是不怎么好维护的,但是根据操作 \(4\) 的询问,观察到该式子后半部分是一个乘法,考虑直接用 bitset 维护每个集合的 \(f(S,p)\)

首先考虑 \(2\) 操作是否一致。\(f(S,p)\) 的实际意义是什么?是 \(S\)\(p\) 的倍数的位出现次数模 \(2\)。这个显然是可以直接异或合并的。

然后考虑 \(3\) 操作。考虑列一个 \(f(S,p)\)\(f(A,p),f(B,p)\) 的关系式,就用刚刚我们推出来 \(S_u\) 与它们的关系式来推即可。

\[\begin{aligned} f(S,p)&=\sum_{p|i}S_i\\ &=\sum_{p|i}\sum_{d}\mu(d)f(A,di)f(B,di)\\ &=\sum_{p|T}f(A,T)f(B,T)\sum_{p|i|T}\mu\left(\frac{T}{i}\right)\\ &=\sum_{p|T}f(A,T)f(B,T)\sum_{pj|T}\mu\left(\frac{T}{pj}\right)\\ &=\sum_{p|T}f(A,T)f(B,T)\left[\frac{T}{p}=1\right]\\ &=f(A,p)f(B,p) \end{aligned} \]

极好!这个乘法在二进制中相当于一个按位与。

剩下一个 \(4\) 操作。不是之前我们才推了一个 \(S_u\) 关于其合并过来的式子吗?我们把其中的 \(f(A,ud)f(B,ud)\) 换成 \(f(S,ud)\),有:

\[S_u=\sum_{d}\mu(d)f(S,ud) \]

我们只需要求这个式子模 \(2\) 的值就行了,所以考虑这个乘法我们依然可以直接搞一个 bitset 来乘,最后统计其 count 就行了。具体地,对于每一个 \(u\) 处理出 \(M_u\) bitset,其中对于所有 \(d\)\(ud\) 位置填 \(\mu(d)\)。注意到是模 \(2\),所以 \(-1\)\(1\) 都填 \(1\) 就行了。

对于每一个数预处理出当只有一个数 \(v\) 在集合中的 \(f\) 函数 bitset。总时间复杂度 \(O(\frac{qv}{\omega}+v\ln v)\)

CF1497D Genius

\(n\) 个问题,每个问题有附加值 \(c_i=2^i,tag_i,s_i\)

定义 \(IQ\) 为一个解决问题时的参数,初始为 \(0\)。解决完 \(i\) 问题后,如果你想解决 \(j\) 问题,你需要保证 \(IQ<|c_i-c_j|,tag_i\not= tag_j\),这样做的权值是 \(|s_i-s_j|\),解决完后 \(IQ\) 会变为 \(|c_i-c_j|\)

初始你可以选择一个问题开始解决,任意问题可以被重复解决,问所有解决的过程结束后的权值和最大值。

\(1\leq n\leq 5000\)

这题我的想法是一次转移一定形如往前搞定一个,然后再往后解决一个,但是有 \(tag\) 的存在,这样做就是错误的,因为需要存每一个数前面被哪个数转移的,原本是可以滚动前缀和优化的,但是 \(tag\) 的存在使得我们不能这样优化。

考虑我们对于所有可能的转移按 \(IQ\) 需求值排序,因为这个题的性质,其实就是 \(i=1\to n,j=i-1\to 1\) 的枚举方式,然后这里直接转移就是正确的,因为每一步转移都满足 \(IQ\) 的限制,而 \(tag\) 的限制判一下就好了。

因为每种转移只可能有一次,且显然无法在一种 \(IQ\) 的转移中成环的转移,所以可以直接互相转移,设 \(f_i\) 为目前解决到 \(i\) 权值最大的值,直接转移即可。时间复杂度 \(O(n^2)\),空间复杂度 \(O(n)\)

CF212D Cutting a Fence

给定一个序列 \(a\),定义一个函数 \(f\) 为:

\[f(k)=\frac{\sum_{x=1}^{n-k+1}\min_{i=x}^{x+k-1}(a_i)}{k} \]

给定 \(q\) 次询问,每次询问 \(f(i)\) 的值。

\(1\leq n\leq 10^6\)

这题有很多做法。我直接暴力分治,用一些双指针获得一个 \(O(n\log n)\) 的复杂度,实际上这个题可以做到 \(O(n)\) 的。

首先我们其实可以预处理出来一个数左边第一个小于它的数,右边第一个小于等于它的数,跨过该点的所有区间答案就是该点的值,同时我们不重不漏地计算到了所有区间。

我们发现如果枚举一边,另外一边的贡献对于 \(f\) 序列是一个区间,这里我们可以差分。根据笛卡尔树启发式合并的结论,我们有:

\[\sum_i\min(r_i-i+1,i-l_i+1)=O(n\log n) \]

其中 \(l_i\)\(r_i\) 就是预处理出来左右数的位置。所以我们可以暴力枚举差分。

当然如果再观察仔细一点,不难发现每个区间的贡献是一样有关系的,这里可以二阶差分处理它。时间复杂度线性。

ARC146D >=<

求构造一个长度为 \(n\) 而每个数取 \([1,m]\) 之间的“完美序列”\(A\) ,使得其中所有数之和最小化。如果不存在,输出 \(-1\)

完美序列的定义:对于所有 \(K\) 个约束条件,对于第 \(i\) 个约束条件,满足以下三者之一:

  • \(A_{p_i}<x_i\)\(A_{q_i}<y_i\)
  • \(A_{p_i}=x_i\)\(A_{q_i}=y_i\)
  • \(A_{p_i}>x_i\)\(A_{q_i}>y_i\)

\(1\le n,m,k\le 2\times 10^5\) 。数据合法。

这个限制非常不好看,考虑把它们化成一样的形式。不难发现我们可以把它们化成两个 \(A\leq x\Leftrightarrow B\leq y\) 的限制,分别是:

\[A_{p_i}\leq x_i-1\Leftrightarrow A_{q_i}\leq y_i-1\\ A_{p_i}\leq x_i\Leftrightarrow A_{q_i}\leq y_i \]

当然你这个时候就可以直接 2-sat 启动,但是需要注意到的是,你需要使得所有数之和最小化,这个放到 2-sat 中是比较难做的。

考虑增量法,即观察到如果只加,一个限制最多被打破一次,考虑我们先将所有值赋为 \(1\),然后如果有限制被打破,那么就把第二个数放到限制之外。这是一种调整的思想,因为打破之后你只可能把这个数放到比某个值大的地方,而值越大打破的限制越多,就越不优。这样做有点像这些限制不得不被打破的感觉,就是这样才能保证最优。随便维护一下即可,复杂度线性或 1log。

CF1422F Boring Queries

见 DS 乱做。

CF811E Vladik and Entertaining Flags

见 DS 乱做。

CF1603C Extreme Extension

对于一个数列,定义一次操作为选择数列中任何一个元素 \(a_i\) ,将这个位置替换成两个正整数 \(x,y\) 满足 \(x+y=a_i\)

定义一个数列的极端值为将这个数列变成不降数列的最小操作次数。

给定一个长度为 \(n\) 的数列 \(a\)\(1\leq a_i\leq 10^5\) ),让你求它的所有非空子段的极端值之和,对 \(\text{998244353}\) 取模。

一个测试点中有多组数据,保证所有数据 \(n\) 的规模总和不超过 \(10^5\)

老题重做。这个题当时我直接就是没做出来,现在大概是会了。

考虑所有非空子段这个东西该怎么处理。一种容易的想法是分治或者扫描线。但是这个题显然和分治不沾边,因为右侧的限制数等价于每个位置的限制数,分治一定劣于扫描线。

注意到一个性质,就是一个点如果分成 \(j\) 份,那么分出来的最大值为 \(\lceil\frac{a_i}{j}\rceil\),最小值为 \(\lfloor\frac{a_i}{j}\rfloor\)。考虑我们对于每个点存一个限制 \(p\),代表这个点分出来最小值为 \(p\) 的方案数和极端值之和。我们发现根据整除分块的性质,至多有 \(O(\sqrt {a_i})\) 个不同的限制,那么倒序 DP 即可。

最后一个细节就是怎么确定一个限制对应的 \(j\) 最小值。按照定义推式子可以得到,设限制为 \(p\)\(j=\lceil\frac{n}{p}\rceil\)。使用滚动哈希表维护,比较卡,时间复杂度 \(O(n\sqrt {a_i})\),当然可以用另外的东西代替哈希表。

CF1603D Artistic Partition

对于给定的正整数 \(l\leq r\),定义 \(c(l,r)\) 为满足下列条件的正整数对 \((i,j)\) 的数量:

  • \(l\leq i\leq j\leq r\)
  • \(\gcd(i,j)\geq l\)

给定正整数 \(k\leq n\)。对所有满足 \(0=x_1 < x_2 < \cdots < x_k < x_{k+1}=n\) 的整数序列 \((x_1,...,x_{k+1})\),计算 \(\sum_{i=1}^kc(x_i+1,x_{i+1})\) 的最小值。你需要回答 \(T\) 组询问。

对全部数据,\(1\leq T\leq 3\times 10^5\)\(1\leq k\leq n\leq 10^5\)

非常牛逼的一道题。

首先是最关键的一个性质,\(k\geq \log n\) 的时候答案就是 \(n\),即没有额外贡献。具体就是发现我们可以 \([2^k,2^{k+1}-1]\) 分段,显然区间中没有不同元素使得 \(\gcd\) 在区间中的。

剩下的,考虑不难发现这个显然有四边形不等式(交叉优于包含),因为包含的时候多了一个 \(\gcd(l-1,r+1)\) 的贡献。考虑推式子计算。

推式子后,移动右端点是 \(O(d(i))\) 的,因为每个点会被遍历到 \(O(\log n)\) 次,所以这个东西均摊下来单次分治复杂度是 2log 的。左端点则比较容易,就是一个欧拉函数的前缀和。

那么使用分治就能做到 \(O(n\log^3 n)\) 的复杂度。

CF845F Guards In The Storehouse

给定一个 \(n\times m\) 的网格,有些位置是障碍(x),有些位置是空地(.)。

可以在每一个空地处放一个摄像头,这个摄像头会向右,向下监视第一个障碍前的所有方格。现在你需要在空地上安排摄像头,使得最多 \(1\) 个空地没有被摄像头监视。输出方案数对 \(10^9+7\) 取模。

\(n,m,nm \le 250\)

注意到 \(nm\leq 250\),所以边长最小值只有 \(16\),这里直接轮廓线就行了。

主要就是观察到某一边可状压的一个性质。

CF1137C Museums Tour

一个国家有 \(n\) 个城市,通过 \(m\) 条单向道路相连。有趣的是,在这个国家,每周有 \(d\) 天,并且每个城市恰好有一个博物馆。

已知每个博物馆一周的营业情况(开门或关门)和 \(m\) 条单向道路,由于道路的设计,每条道路都需要恰好一个晚上的时间通过。你需要设计一条旅游路线,使得从首都:\(1\) 号城市开始,并且当天是本周的第一天。每天白天,如果当前城市的博物馆开着门,旅行者可以进入博物馆参观展览,否则什么也做不了,这一天的晚上,旅行者要么结束行程,要么通过一条道路前往下一个城市。当然,旅行者可以多次经过一个城市

要求让旅行者能够参观的不同博物馆数量尽量多(同一个城市的博物馆参观多次仅算一次),请你求出这个最大值。

\(1\le n\le 100,000\)\(0\le m\le 100,000\)\(1\le d\le 50\)

考虑直接建一个按题意的 \(k\) 层循环分层图。不难发现对于一个点,如果有 \(a\) 时刻可达 \(b\) 时刻,那么 \(b\) 时刻也一定可达 \(a\) 时刻。所以建出分层图之后缩点求出每个连通块的答案,这个时候做一下去重,然后发现答案就是点权最长路了。

为什么?因为这个结构满足如果某个点 \(a\) 时刻不可达 \(b\) 时刻,那么 \(b\) 时刻就不可达 \(a\) 时刻,所以 \(a\) 时刻和 \(b\) 时刻的连通块根本互不连通,最长路中也一定只会连接其中一个联通块。

直接缩点拓扑排序即可。注意这题卡巨大空间,需要链式前向星。还卡巨大栈空间,需要 inline

时间复杂度 \(O((n+m)d)\)

CF884E Binary Matrix

给定一个 01 矩阵,求 1 的四连通块个数。

\(1\leq n\leq 2^{12},1\leq m\leq 2^{14}\)。空间限制 16MB。

这个空间限制使得不能直接 DFS。

考虑沿用之前维护区间连通块的那个题的线段树思路,将并查集的过程滚动掉,同时将每个点的 \(fa\) 尽量往目前的那一行靠,这样容易实现。时间复杂度为 \(O(nm\alpha(m))\)

CF1946F Nobody is needed

见 DS 乱做。

CF1500C Matrix Sorting

给你两个 \(n\times m\) 的矩阵 \(A,B\)\(1\le n,m\le 1500\)),矩阵的元素均为 \([1,n]\) 内的整数。

每一次操作你可以选定一列作为每一行的关键字,按照关键字从小到大的顺序把所有行排序得到一个新矩阵。这里使用的排序是稳定的,即如果有两行的关键字相同,则按照在原矩阵的先后顺序排序。

你可以进行不超过 \(5000\) 次操作,问你能否将 \(A\) 变成 \(B\)。不能变成输出 \(-1\),否则输出一种可行的操作序列。

很巧妙的一个构造题。

首先不难发现目标矩阵如果和原矩阵不一样的话,至少会有一列满足是按升序排序的。

首先用哈希和这个升序的列得到目标矩阵的行在原矩阵的编号。如果用相同的行可以直接不管。

我们定义解决两个数的顺序为经过一次排序之后后面都不会改变这两个数的顺序,并且在最终的排序中这两个数的顺序正确。显然只需要在已排序列讨论相邻的两个数的顺序就行。

倒序考虑所有排序操作。显然一次排序是可以解决一些数对的。我们把需要解决的数对(因为只需要相邻的,所以是 \(O(n)\) 个)单独拎出来建点。然后对于每一列讨论这些所有的数对,如果满足排序之后能解决这两个点的顺序,那么这个列的点连向对应数对的点。如果反而会倒置顺序,那么就对应数对连向这个列的点,表示我们需要后面先解决完这些点对才能考虑对这一行排序。我们在原矩阵最后加一列 \(1\sim n\),对我们建出来的图拓扑排序,如果能排到最后这一列的,那么直接将拓扑序倒着输出即可。

需要注意的是,这里的拓扑排序和传统意义上的拓扑排序不同。因为解决一个点对的过程只需要一次,所以只需要一个入度被选就能选到解决点对的点。

CF1713F Lost Array

抽象高级题。

给出一个从 \(1\)\(n\) 的数组 \(a\)。有一个从 \(0\) 开始标号的大小为 \((n+1)\times (n+1)\) 的矩阵 \(b\),通过以下方式生成:

  • 对于 $0 \leq i \leq n , b_{i,0} = 0 $。
  • 对于 $1 \leq i \leq n , b_{0,i} = a_{i} $。
  • 对于 \(1 \leq i, j \leq n , b_{i,j} = b_{i,j-1} \oplus b_{i-1,j}\)

现在,给出 $ b_{1,n}, b_{2,n}, \ldots, b_{n,n} $,试还原出一个满足条件的 \(a\) 数组,或者报告无解。

\(1\leq n\leq 5\times 10^5\)

真的很抽象啊。

首先尝试直接描述题意,首先把矩阵的右上角当做原点,也就是说把 \(a\) 倒序看。发现一个位置 \(a_i\) 贡献到目标 \(b_j\),需要走 \(i+j\) 步,一共有 \(\binom {i+j}{i}\) 种贡献方式。这里显然只有奇数次贡献才真正贡献到了,所以这里我们需要让这个组合数为奇数。

根据库默尔定理(或者手玩),发现当且仅当 \(i\operatorname{and}j=0\) 时才能满足奇数的限制,这也就是说 \(i\)\(j\) 补集的子集。因为是异或,所以直接往回做一遍子集异或就行了。根本不是!你这里的补集出了问题,因为是补集,所以无论是你得到的补集信息还是你推到的补集信息,都是需要整个 \(2\) 的正整数次幂的信息才能得到。而你只有前 \(n+1\) 项,显然不够。

然后就是神奇 Ad-hoc 部分了。注意到什么是可以直接做逆回去的,显然是只涉及到 \(0\sim n\) 的信息的变换,即没有什么补集之类的神奇变换。拆开 \(\binom {i+j}{i}\)。几何意义上,我们先贡献到该矩阵变换原点之后的主对角线(即原来的副对角线)上,然后再贡献到 \(b\)。惊喜的发现,这里我们的贡献就变成了 \(x\)\(y\) 的子集的形式,这样我们只涉及到 \(0\sim n\) 的超集异或或者子集异或,所以没有什么煞笔的补集问题,直接做回去即可。复杂度 1log。

posted @ 2024-10-10 20:55  xingyu_xuan  阅读(18)  评论(2编辑  收藏  举报