C
第 \(i\) 个同学一开始有第 \(i\) 份礼物,每个同学对礼物的喜爱度都有排序。
\(q\) 次询问把所有人划分为两个集合,集合里的人可以互相交换礼物,问方案数使得每个人喜爱度不降。
\(n\le 18\)。
若 \(i\) 能将礼物给 \(j\) 那么连一条 \(i\to j\) 的边,相当于最后求置换环组成图的方案数。
首先我们要求出集合 \(s\) 为一个置换环的方案数,设 \(f_{S,u,v}\) 表示集合 \(u,v\) 分别为起点/终点的方案数。
转移显然,最后看 \(v\to u\) 是否存在边。但是这样每个环会被算其大小次,时间被浪费。
不妨直接钦定 \(s\) 中最小的为起点,复杂度减少 \(O(n)\)。
最后做子集 dp,只需要提出一个基准点,枚举其所在集合即可。
D
有向图,问多少个闭合子图满足点的编号连续。\(n,m\le 3e5\)。
两种思路:枚举闭合子图,看是否连续;枚举连续的区间,看是否为闭合子图。
后者更适合,设 \(c_i,d_i\) 表示其出边最小/最大的编号,那么 \(\min(c_i)\ge l,\max(d_i)\le r\) 就满足条件。
计数上面那个东西,枚举右端点,先将 \(\max(d_i)\le r\) 二分出来。
然后 \(\min(c_i)\ge l\),即 \(\min(c_i)-l\ge 0\),而 \(\max(\min(c_i)-l)\le 0\),即求最大值的个数,上线段树即可。
然后用单调栈维护每个 \(\min(c_i)\) 对应的区间。