今天这把同样一坨。A 题看成一个二分图匹配这种 dp 的模型,而且后续转化为 DAG 定向计数也比较难发展。B 题更史了完全忘记了这种研究方法,执着于研究函数结构去了。然后 C 题因为不太模型化导致不会分析啥也没写。
反思一下呢,大概就是没有多个角度想吧,总是死磕一个方向,但是总会遇到阻碍。还有就是别摆烂了,注意时间分配的问题。
A
给定两个 \(1\sim n\) 的排列 \(p,q\),一个长度为 \(n\) 的 01 串 \(s\) 是合法的,当且仅当至少存在一个 \(1\sim 2n\) 的排列\(a\),满足 \(a\) 的前 \(n\) 个数离散化后的排列是 \(p\),\(a\) 的后 \(n\) 个数离散化后的排列是 \(q\),且若 \(s_i=1\) ,则 \(a_i> a_{i+n}\),否则 \(a_i<a_{i+n}\)。令 \(f(p,q)\) 表示合法的 01 串的数量。现在 q 中的一些数是未知的,求对于所有可能的 \(q\) ,\(f(p,q)\) 之和。\(n\le 500\)。
考虑已知 \(q\) 怎么做。首先现将 \(p\) 重标号,可以看做有两条链,然后有一个匹配,要你给每条边定向使得无环。
考虑求方案数。据说这是一个 DAG 计数问题。考虑把 \((p_i,q_i)\) 放到平面上去研究。
然后你发现若一个左上的点满足 \(p_i>q_i\),但是右下的点满足 \(p_j<q_j\) 这肯定不可能。
所以相当于有一条分界线分开了平面上的点,跟 qoj 9222 很像。考虑把分界线对应到 01 序列上。
可以把一条分界线“贴着”的点拿出来作代表,而这些点右下的全部取 \(1\),相当于构成双射。
而这些”贴着“的点怎么计数,发现这就是上升子序列的个数好吧,然后就做完了。
考虑 \(q_i\) 未知的情况。我们肯定不能把 \(q_i\) 压进状态里对吧,不妨将一种 q 按照其可能合法的 01 序列分类。
也就是拆贡献了,对于一种 01 序列考虑能对应多少种 \(q\) 即可。
一种 01 序列用 LIS 表示的话,贡献就是不在 LIS 里数个数的阶乘。
设 \(dp_{i,j,k}\) 表示前 \(i\) 个数选了 \(j\) 个进入 LIS,最后一个是 \(k\) 的方案数即可。这里 \(j\) 不包括已经钦定的点。
B
有一个序列,值域 \([1,m]\),你进行操作:将两个相邻的 \(k\) 合并为 \(k+1\),或者任意删掉一些位置。
\(q\) 次询问每次询问一个区间的所有子区间能合并为只剩一个 \(k\) 的个数。\(n,m,q\le 2e5\)。
先考虑判定问题,我们很容易有一种递归判定的方式,就是能合并为 \(k\) 是分为两个不交区间能合并为 \(k-1\)。
然后有一种思路就是取出所有极短的能凑出 \(k\) 的区间。由于这个题肯定与势能有关所以区间总数是较少的。
而区间查询就是类似的维护二维平面上的阶梯型,这个还是比较难处理。
还有一种思路就是固定一个端点然后观察。考虑维护 \(f_{l,j}\) 表示左端点为 \(l\),能凑出 \(j\) 最左的右端点。
这个还是很好做的,\(f_{l,j}=\min(f_{{f_{l,j-1}+1},j-1},nxt_{l,j})\),这个 dp 应该是相同值很多的,然后可以维护连续段。
对于所有 \(j\) 的段数和大概也是 \(O(n)\) 或者 \(O(n\log n)\)?那么后面就好做了。
对于询问 \([x,y]\) 答案的计算也就是 \(\sum_{i=x}^y r+1-\min(f_{i,j},r+1)\)。这个可以扫描线做。
C
一条长度为 \(L\) 的链,每个点容量为 \(C_i\),有 \(n\) 个人每次出现在第 \(X_i\) 条边,你需要将其分配到两端点之间不满的一个,如果都是不满的就任意选,如果都满的就算了。你需要计算两端点都满的人最大有多少个。
\(n,L,C_i\le 8000\)。
这是一个最优化问题,考虑描述一个方案。题目条件是最小化,而我们求最大值,说明要进行转化。
一个常见的思路是转化为对于满足某条件的所有集合进行 dp。相当于满足题目最小化条件,最大化代价。
考虑将一个方案表示为序列 \(t_i\) 表示第 \(i\) 个点放满的时间。那么第 \(j\) 个人贡献当前仅当 \(j>\max(t_i,t_{i+1})\)。
考虑 \(t\) 如何合法,相当于将人和点进行匹配。考虑 Hall 定理 \(|S|\le |N(S)|\) 就是 \(\sum \max(t_i,t_{i+1})\le \sum C_i\)。
显然 \(S\) 必须是一个区间,要不然根据抽屉原理必定有一个子区间不合法。所以可以转化为最小子段和。
那么对于 \(t\) 序列做 dp 即可。所有点的 \(t_i\) 取值集合大小是 \(O(n)\)。每个 \(t_i\) 记录 \(t_{i}\) 个后缀和,此时的最值。
代价是 \(\max(t_i,t_{i+1})\) 分讨取到的是哪个,转移考虑进行前后缀 \(\max\) 优化即可。