CSP模拟52 & A 层联测 9
2023NOIP A 层联测 9
长春花
观察大样例可以发现,函数 \(f(x)\) 的值很小,那么可以考虑暴力枚举。
用一个桶存一下平方数对 \(p\) 取模的值是否存在,那么可以选择从小到大枚举 \(a\),找到第一个存在的 \(b\)。
紫罗兰
考虑什么情况下会出现环,当两个点已经连通时,再在这两个点之间加一条边,那么会产生环(不一定是简单环)。
考虑用并查集维护两点是否连通,依次加边。
如果两个结点已经连通,那么可以 BFS 找这两个结点间最短路径,新产生的环的长度即为两点间最短路径长度加 \(1\),这一过程是 \(O(n)\) 的;
如果两结点尚未连通,则无需 BFS,直接建边并查集维护连通性即可。
最多 BFS 次数不会超过 \(m\) 次,那么复杂度不会超过 \(O(nm)\),优于题解的 \(O(n(n +m))\)。
天竺葵
本质上是一个带权的最长上升子序列。
先考虑 \(O(n^2)\) 做法,设 \(dp_{i,j}\) 表示前 \(i\) 个数选出长度为 \(j\) 的子序列时,末尾数的最小值。
那么满足 \(a_i > dp_{i-1,j-1} \times b_{j-1}\) 时,有转移 \(dp_{i,j}=\min \left\{ dp_{i-1,j},a_i \right\}\)。
考虑怎么优化,可以发现 \(i\) 相同时,\(dp_{i,j}\) 的值随 \(j\) 单调递增,即对于 \(j < k\),有 \(dp_{i,j} < dp_{i,k}\)。
那么考虑,对于 \(dp_{i-1,j-1} > a_i\) 时,无法转移,显然找不到这样一个 \(b_{j-1}\) 使得序列合法。
对于 \(dp_{i-1,j-1} \leq a_i\),才有可能转移,那么我们找到第一个大于 \(a_i\) 的位置进行判断并转移。
风信子
考虑复习超级钢琴。
设一个三元组 \((id,l,r)\),\(id\) 表示左端点,\(l,r\) 表示右端点的候选区间。
我们要找到前 \(k\) 个最优的答案,假设我们找到了第一个解的右端点 \(x\),那么 \(\left[ l,x \right)\) 和 \(\left(x,r \right]\) 仍然是一个候选的答案区间,我们把它们放进堆里再去选择下一个答案。
那么对于这道题也用到了这样的思想,左右端点各属于一个区间,那么这个解的集合成为了一个矩形。
假设我们已经有了其中一个解 \((x,y)\),那么考虑去掉这个解之后的候补答案集合是什么。
有两种情况是容易获得候补答案集合的,即左右端点区间重合或相离。
另外的情况就是左右端点集合有相交的部分,可以考虑将其转化为容易处理的类型。
设左右端点区间分别为 \(\left[ l_1,r_1 \right]\) 和 \(\left[ l_2,r_2 \right]\),有 \(l_1 \leq l_2 \leq r_1 \leq r_2\)。
那么我们可以把左端点的分为 \(\left[ l_1,l_2 \right]\) 和 \(\left[ l_2,r_1 \right]\);将右端点分为 \(\left[ l_2,r_1 \right]\) 和 \(\left[ r_1,r_2 \right]\)。然后可以让左端点两个区间与右端点区间分别组合,容易发现每一个组合都是相离的。
最后考虑两种容易处理的情况,设最优解位于 \((x,y)\)。
左右端点所在区间重合:
左端点 \(\in \left[ l,x-1 \right]\),右端点 \(\in \left[ l,x-1 \right]\)(\(x > l\));
左端点 \(\in \left[ l,x-1 \right]\),右端点 \(\in \left[ x,r \right]\)(\(x > l\));
左端点 \(\in \left[ x,x \right]\),右端点 \(\in \left[ x,x \right]\)(\(x \neq y\));
左端点 \(\in \left[ x,x \right]\),右端点 \(\in \left[ x+1,y-1 \right]\)(\(x < y - 1\));
左端点 \(\in \left[ x,x \right]\),右端点 \(\in \left[ y+1,r \right]\)(\(y<r\));
左端点 \(\in \left[ x+1,r \right]\),右端点 \(\in \left[ x+1,r \right]\)(\(x < r\))。
左右端点所在区间相离:
左端点 \(\in \left[ l_1,x-1 \right]\),右端点 \(\in \left[ l_1,r_1\right]\)(\(x > l_1\));
左端点 \(\in \left[ x,x \right]\),右端点 \(\in \left[ l_2,y-1 \right]\)(\(y > l_2\));
左端点 \(\in \left[ x,x \right]\),右端点 \(\in \left[ y+1,r_2 \right]\)(\(y<r_2\));
左端点 \(\in \left[ x+1,r_1 \right]\),右端点 \(\in \left[ l_2,r_2 \right]\)(\(x < r_1\))。
时间复杂度 \(O((n+(\sum k))\log n+(\sum k)\log (\sum k))\)。