此后再无 NOIP 模拟赛。
A
给一个包含 \(n\) 个布尔变量的后缀逻辑表达式,给定这 \(n\) 个变量的初值,请你求出:若想改变表达式的值,最少需要改变(取反)其中多少个变量的值。
树形 dp,只需要设 \(f_u\) 表示 \(u\) 子树的答案。
B
给定一个排列,判断是否存在等差子序列。
考虑枚举中间的那个数,那么,如果存在等差子序列那么就存在 \(a_i-k,a_i+k\) 分居同一侧。
考虑正难则反。如果不存在,那么对于所有 \(k\),\(a_i-k,a_i+k\) 都所处位置相同,考虑用 \(0,1\) 代表两侧。
判断序列的相同考虑哈希,我们从左往右扫,线段树维护哈希即可。
C
对于一个排列 \(P\),以及一个点集 \(S\),定义:
\(set(S)=\{x|\exist l,r\in S,l<r,\min_{a_l\sim a_r}=x\}\),\(len(S)=|set(S)|\)。
\(f(S)=1\) 当且仅当 \(|S|\le 1\) 或 \(\exist i\in S,f(S-i)=1 \wedge len(S)=len(S-i)+1\)。
\(dis(S)=\sum_{T\subseteq S,f(T)=1}[len(S)=len(T)]\),求 \(\sum_S dis(S)\)。
\(f(S)=1\) 的条件显然为 \(len(S)=|S|-1\)。
考虑建出笛卡尔树,那么 \(len(S)\) 的意义是建出虚树后非叶子节点的个数。
那么 \(f(S)=1\) 的话,限制是对于每个点 \(u\),\(u\) 本身,左子树,右子树不能同时有点。
考虑拆贡献到每个 \(f(T)=1\) 处。考虑给 \(T\) 加点使得 \(len(T)\) 不变。有两种情况:
其一是左右子树都被选了,那么在此时根节点可以选;
其二是根被选了,那么没被选的那个子树可以任选一个点出来。
所以一个 \(f(T)=1\) 的贡献是若干个位置的积。设 \(dp_u\) 表示 \(u\) 子树的点的所有子集的贡献积的和。
那么,\(dp_u=1+dp_{ls}+dp_{rs}+2\times dp_{ls}\times dp_{rs}+dp_{ls}\times (siz_{rs}+1)+dp_{rs}\times (siz_{ls}+1)\)。
\(2\times dp_{ls}\times dp_{rs}\) 指根的选不选;\(dp_{ls}\times (siz_{rs}+1)+dp_{rs}\times (siz_{ls}+1)\) 指另一个子树选一个点/不选。
D
\(n\times m\) 的网格,\(q\) 次给若干行或若干列染颜色,统计有多少对格子边相邻且颜色相同,有多少对格子角相邻且颜色相同。\(n,m,q\le 1e5\)。
边相邻的话,考虑时光倒流,行列分别统计。
角相邻我不会,线段树,扫描线,