ARC198 做题记
A (I hate 1)
题意
给定 \(n\),求大小最大的 \(\{1,2,\cdots,n\}\) 的子集 \(S\),使得不存在 \(x,y\in S\),使得 \(x\equiv 1\pmod y\),并给出构造。
\(1\le n\le 2\times 10^5\)。
题解
当 \(n=1\) 时,集合为 \(1\)。
否则注意到 \(1\) 不可选,相邻不可同时选,于是大小有上界 \(\left\lfloor\dfrac{n}{2}\right\rfloor\)。
并且容易给出构造 \(S=\left\{2,4,6,\cdots,2\lfloor\frac{n}{2}\rfloor\right\}\)。
B (Rivalry)
题意
给定由 \(X\) 个 \(0\),\(Y\) 个 \(1\) 和 \(Z\) 个 \(2\) 构成的长为 \(X + Y + Z\) 的非负整数序列 \(A = (A_1, A_2, \dots, A_{X+Y+Z})\)。请判断是否存在满足以下条件的序列:
- \(\forall i,A_{i-1}\) 和 \(A_{i+1}\) 中严格小于 \(A_i\) 的数的个数恰好为 \(A_i\) 个。
其中,定义 \(A_0 = A_{X+Y+Z}\),\(A_{X+Y+Z+1} = A_1\)。
\(T\ge 2\times 10^5\) 组多测,\(0\le X,Y,Z\le 10^9,X+Y+Z\ge 3\)。
题解
分别考虑 \(0,1,2\) 的限制。
-
\(0\) 对左右 没有任何限制。
-
\(1\) 限制了左右必须恰好 \(1\) 个 \(0\)。
-
\(2\) 限制了左右必须没有 \(2\)。
\(0\) 是最宽松的,于是我们考虑先放 \(0\),然后插入 \(1,2\)。
观察两个相邻的 \(0\) 之间的情况。
-
\(1\) 的个数 \(\le 2\),否则违反了 \(1\) 的限制。
-
最多只有 \(1\) 个 \(2\),否则两个 \(2\) 之间得有 \(1\) 间隔,然后违反了 \(1\) 的限制。
根据这个写一下限制:
-
\(2X\ge Y\)
-
\(X\ge Z\)
-
\(2\mid Y\text{ or }Z>0\),这条是因为若两个 \(0\) 之间只有一个 \(1\),那么 \(1\) 一定要有个 \(2\) 垫着。
C (Error Swap)
题意
给定两个长为 \(n\) 的序列 \(a,b\),每次能对 \(a\) 操作 \((i,j):(a_i,a_j)\gets (a_j-1,a_i+1)\)
请构造方案使把 \(a\to b\),或判断无解。
\(1\le n,a_i,b_i\le 100\),需要保证操作次数 \(\color{red}{Q\le 31000}\)。
题解
先分析 \(31000\sim 3nV\) 这样的东西,不过对于我做法其实没啥用。
你发现操作相当于 swap(a[i],a[j]),a[i]--,a[j]++,但是事实上你不希望 swap。那就交换两次交换回来!
比如你增量构造,你让 \(a_{1\sim k-1}=b_{1\sim k-1}\),接下来你要让 \(a_k=b_k\)。
你需要在不改变 \([1,k-1]\) 的情况下实现 a[i]-- 或 a[i]++。
具体的,你操作 \((i,i+1),(i+1,i+2),(i,i+2)\),即可 a[i]++,减少也是同理。
最后剩 \(a_{n-1}\) 和 \(a_n\),考虑让 a[n-1]++,a[n]-- 或 a[n-1]--,a[n]++。
比如前者,操作 \((n-1,n),(n-2,n-1),(n-2,n),(n-2,n-1)\) 即可。
但是此时值域有可能达到 \(nV\),次数理论最坏是 \(\mathcal{O}(n^2V)\) 的,过不去。
于是你每次找到一个最小的 \(|a_k-b_i|,k\ge i\),然后操作 \((i,k)\) 再把 \(a_k\to b_i\) 即可。
这样贪心就比较对,能通过此题,有题解分析次数是跑不满的 \(\mathcal{O}(nV\log n)\) 的,比较厉害。
D (Many Palindromes on Tree)
题意
给定一颗 \(n\) 个点的树,你要给每个点赋一个整数点权,要满足 \(m\) 个条件:
\(\forall i\in [1,m],x_i\leftrightarrow y_i\) 路径上的点权依次排列下来为 回文串。
定义 \(f(x,y)\) 表示你赋值后 \(x\leftrightarrow y\) 路径是否为 回文串。
你需要最小化 \(\sum\limits_{1\le x,y\le n} f(x,y)\),只需输出这个值即可。
\(1\le n\le 3000,0\le m\le \dfrac{n(n-1)}{2}\)
题解
只需并查集合并 相等节点 即可,但是直接维护是 \(\mathcal{O}(n^3)\) 的。
考虑若 \((u,v)\) 被合并过,则 \((u,v)\) 各内收一个位置也一定合并过,以此类推 \(\cdots\)
于是我们只需记录 \((x,y)\) 是否被合并过即可,然后并查集维护。这样总共只会算 \(\mathcal{O}(n^2)\) 次。
最终算答案也是同理,\((u,v)\to (u,v)\) 各内收一个记忆化搜索即可。复杂度 \(\mathcal{O}(n^2)\),常数略大。
- 注意 是否被合并过 和并查集属于同一个集合,是两个概念。因为可能 \((u,v),(u,w)\) 合并,然后 \((v,w)\) 同属一个并查集,但是 \((v,w)\) 未被合并,要重新算。
E (Monotone OR)
题意
给定一个数列 \(S = \{ s_1, s_2, \dots, s_m \}\)。
初始 \(x=0\),你可以进行以下操作任意次数,求使得 $ x = 2^n $ 的不同方案数,对 \(998244353\) 取模。
- 选择一个 \(i\in [1,m]\),将 \(x\gets (x \ \mathrm{or} \ s_i) + 1\)。
\(1\le n\le 24,m\le \min(2^n,2\times 10^5),0\le s_1<s_2<\cdots<s_m<2^n\)。5s。
题解
记 \(f_i\) 表示 \(x=i\) 的方案数,\(f_{0}=1\)。
显然 \(\text{or}\) 好做,\(\text{or}+1\) 不好做。
定义 \(a_{x}\) 表示 \(x\) 在 \(s\) 中是否出现。建立辅助数组:\(g_{i-1}=f_{i}\)。
那么 \(g=f*a\),其中 \(*\) 是 \(\text{or}\) 卷积。
显然 \(\text{FWT}\) 一下:\(\text{FWT}(g)=\text{FWT}(f)\cdot \text{FWT}(a)\),其中 \(\cdot\) 是点乘。
记 \(A=\text{FWT}(a)\),那么 \(\sum\limits_{T\sube S} g_T=A_S\sum\limits_{T\sube S} f_T\Rightarrow g_S=A_S\sum\limits_{T\sube S} f_T-\sum\limits_{T\subsetneq S} g_T\)
一眼这东西是 半在线高维前缀和,但是具体怎么做呢,我刚开始还真不会!
\(\text{FWT}\) 过程类似 \(\text{DFT}\) 过程,也可以理解为一个分治结构,自底向上 转移。
下面记 \(F_S,G_S\) 表示要求解的 \(\sum\limits_{T\sube S} f_T,\sum\limits_{T\sube S} g_T\)。
我的初步想法:
比如我们递归到 solve(l,r),现在要解决 \([l,r]\) 中的 \(f,g\)。
-
先递归左侧
solve(l,mid),解决 \([l,mid]\) 中的 \(f,g\)- 在递归到 \(l=r\) 时,我们先让 \(F_{l}\overset{+}{\longleftarrow} f_l\),然后求出 \(f_{l+1}=g_l=A_{l}F_{l}-G_l\),然后 \(G_{l}\overset{+}{\longleftarrow} g_l\)
-
然后根据 \(\text{FWT}\) 转移,这一层我们让 \((F,G)_{mid+1+k}\overset{+}{\longleftarrow} (F,G)_{l+k}\)
-
递归右侧
solve(mid+1,r)
但是你写一发,发现上述过程是 错误的。
为啥呢?举例 \(2^n=4\) 的时候,你
solve(2,3)的时候,你发现,你的 \(G_2\) 已经是 \(g_{0}+g_{2}\) 了,但是你的分治结构要求 \(G_2=g_2\)原因是递归的右区间的时候,左半边的贡献多算了,会导致右边向上转移时候错误。
解决方案也很简单,递归到 \(l=r\) 的时候,令 \((F,G)_{l}=(f/g)_{l}\),然后递归完 \([mid+1,r]\) 后重新贡献 \([l,mid]\to [mid,r]\)
写一个正确过程,当前 solve(l,r)。
-
先递归左侧
solve(l,mid)-
在递归到 \(l=r\) 时,我们先让 \(F_{l}\overset{+}{\longleftarrow} f_l\),然后求出 \(f_{l+1}=g_l=A_{l}F_{l}-G_l\),然后 \(\color{red}{(F,G)_{l}=(f/g)_l}\)。
因为 \(f_{0}=1,f_l\) 在求解 \(l-1\) 的时候就被 \(g_{l-1}\) 求出了。保证了递归到 \(l\) 的时候 \(f_{l}\) 值已经求出。
-
-
然后根据 \(\text{FWT}\) 转移,这一层我们让 \((F,G)_{mid+1+k}\overset{+}{\longleftarrow} (F,G)_{l+k}\),也就是算 \([l,mid]\to [mid+1,r]\) 的贡献。
-
递归右侧
solve(mid+1,r) -
再进行一次第二步的 \([l,mid]\to [mid+1,r]\) 的贡献,因为你在叶子处 \((F,G)=(f,g)\) 重新赋初值了。

浙公网安备 33010602011771号