省选补题
D1T1
神必题,被神必 CCF 卡常了。
我有一个非常高妙的正确的 \(O(n \log n)\) 做法,目前 uoj 上还没有被 hack。
懒的说这题(说不定心情好又会写上去),就贴个代码吧
目前这份代码在 uoj 上还是最劣解,欢迎来尝试跑的比我慢(雾)。
upd:被卡常了,咕咕咕了。
D1T2
被一个差分约束打爆了。
4 个元素怎么差分约束啊。
首先不考虑 \(a_{i,j}\) 的限制,那么是必定可以构造出一组解的,称这组解为 \(c\)。
那么的话,我们考虑在这个 \(b\) 上进行一些调整使它满足这个限制。可以发现,给某一行所有奇数位置加一,偶数位置减一,那么也会满足条件,每一列同理。容易想到并且可以证明,所有可能的情况都可由以上两种操作得到。设 \(x_i\) 表示第 \(i\) 行加多少,\(y_i\) 表示第 \(j\) 行加多少,那么最后的答案就是
\(\begin{bmatrix}c_{1,1}+x_1+y_1,c _{1,2}-x_1+y_2,&\cdots\\c_{2,1}+x_2-y_1,c_{2,2}-x_2-y_1,&\cdots \\ \vdots&\ddots&\vdots\end{bmatrix}\)
这样子的性质。
但是这还是不怎么能搞,毕竟差分约束只能搞相减的,那么考虑把一些 \(x_i\) 和 \(y_i\) 反过来(可以简单理解成乘上 \(-1\)),使得每个位置 \(x_i\) 和 \(y_j\) 前的系数恰好是一正一负即可。随便凑一下发现把奇数行的 \(x_i\) 与偶数列的 \(y_i\) 反过来即可,然后跑个差分约束求个答案就完了。
code,97 分可能是 SPFA 被卡了?反正官方数据是能过的。
D1T3
图论题,果然啥都不会。
考虑这个 \(f(i,G)\) 的本质:经过手玩后可以发现,对于一对点 \((u,v)\)(\(u<v\)),\(u\) 对 \(v\) 有贡献当且仅当 \(u\) 可以通过所有 \(\ge u\) 的点到达 \(v\),下面来证明这个结论:若 \(u \to v\) 或者 \(v \to u\) 必需经过的最小的点为 \(x\),那么若 \(x\to v\),\(v \to x\) 的路径都存在那么本来就会被删掉,否则的话相当于存在一个 \(u \to v \to u\) 并且经过 \(x\) 的环,显然也是有 \(x \to v\) 或者 \(v \to x\) 的路径。
然后每次删掉一条边显然可以转化成倒序操作后加边,那么对于一对点 \((u,v)\),他一定是在加入了第 \(x\) 个边后有贡献,那么这个边必然是越先加越好:那就是相当于对于每对点 \((u,v)\),找出 \(u\to v\) 上只经过 \(\ge \min (u,v)\) 的点中编号最小的边最大。倒序枚举中转点 \(k\),用 floyed 解决即可。时间复杂度 \(\mathcal{O}(n^3+m)\),稍微精细点实现就可以过了,所有答案还要加上 \(n\)(自己对自己肯定有贡献)。
code。
D2T1
数据结构,神必的 CCF 又把部分分弄错了,被这题打爆了。
下文中令 \(n,m,q,c\) 同阶。
首先令 \(t_{p_i}=i,a_i=t_{a_i}\),那么就相当于找一个 \(1-ans\) 的子序列。
首先考虑一个链上的情况,对于一个询问 \((u,v)\),不妨令 \(u \le v\),那么显然对于每个点 \(i\),它需要跳到它之后的第一个 \(j\) 满足 \(a_j=a_i+1\),这部分可以用桶解决,然后用倍增 \(f1_{i,j}\) 表示点 \(i\) 跳 \(2^j\) 次之后的结果。对于每次询问 \((u,v)\),找到 \(u\) 之后第一个为 \(1\) 的节点然后从这个点开始跳,就可以在 \(O(n\log n)\) 的时间复杂度内求出答案。
考虑上树。对于一个询问 \((u,v)\),可以将其拆成 \(u \to lca\) 的上行路径和 \(lca \to v\) 的下行路径。上行路径直接可以通过上述的方法解决,记此时的答案是 \(ans\),然而下行路径呢?直接考虑 \(lca \to v\) 是比较困难的,考虑二分答案。
不难发现,每次 \(lca \to v\) 需要让当前答案递增,那么反着考虑,等价于 \(v \to lca\) 让当前答案递减,类似的,设一个 \(f2_{i,j}\) 为点 \(i\) 跳 \(2^j\) 次的结果,每次跳到它祖先中的最深的 \(j\) 满足 \(a_j = a_i-1\),然后对于每一个 \(mid\),check 的过程就是让它往前跳然后看能否跳到 \(ans+1\) 这个节点,这样就完成了……吗?
还有一个问题:对于每个 \(mid\),你要在 \(u\) 的祖先中找到第一个 \(a_i=mid\) 的点 \(i\),然后这样子时间复杂度就爆炸了……
考试的时候我想到这里就不会了,最终只打了暴力+链的分。实际上有个非常简单的方法,把所有询问离线下来然后再 dfs 的过程中,用一个桶 \(t\),\(t_i\) 表示当时的节点祖先中第一个 \(a_j=i\) 的 \(j\),一边 dfs 一边询问,就可以做到 \(O(n \log^2 n)\) 的时间复杂度。
代码也蛮好写的,这种方法可能是最好写的(相比于树剖和点分治),而且跑的也蛮快,可惜考试的时候差了最后一步……
code。
D2T2
被一个状压打爆了。
考虑暴力枚举全排列,判断是否可行的时候,如果这个排列是 \(p_{1...n}\),那么每次贪心的让 \(b_i\) 最小,即 \(b_{p_i}=\max(b_{p_{i-1}},b_{p_{i-1}}+a_{p_{i-1}}-a_{p_i}+[p_i>p_{i-1}])\),如果有多余的那么全部给最后一个就好了,时间复杂度 \(O(n!)\)(考场上只写了这个)。
观察数据范围,考虑状压。一个朴素的想法是 \(dp_{S,i,j,k}\) 表示当前集合是 \(S\),上一个数是 \(i\),上一个 \(b_i=j\),\(\displaystyle \sum_{p=1}^i b_i =k\) 的方案数,然后发现这样子状态是 \(O(2^nn^2m^2)\) 的,甚至跑不过暴力。
考虑优化,注意到 \(b_{p_i}=\max(b_{p_{i-1}},b_{p_{i-1}}+a_{p_{i-1}}-a_{p_i}+[p_i>p_{i-1}])=b_{p_{i-1}}+\max(0,a_{p_{i-1}}-a_{p_i}+[p_i>p_{i-1}])\),令 \(c_i=\max(0,a_{p_{i-1}}-a_{p_i}+[p_i>p_{i-1}]\),那么 \(b_i\) 就是 \(c_i\) 的前缀和,\(\displaystyle \sum_{i=1}^n b_i = \sum_{i=1}^n (n-i+1) \times c_i\),只要知道 \(c_i\) 就可以了,然后发现,\(c_i\) 只和 \(p_{i-1},p_i\) 有关,然后就能设计一个简单的状态 \(dp_{S,i,j}\) 表示当前集合为 \(S\),上一个数是 \(i\),\(\displaystyle \sum_{p=1}^i b_p=j\) 的方案数,每次枚举前一个数转移就可以了,时间复杂度 \(O(2^n n^2 m)\)。
code。
吐槽:感觉这题仔细想一想还是能够想出来了,但是考场上因为花大量时间在 T1 上,就只写了 \(60\),还是比较可惜的。
D2T3
一年前我在 ZJOI2021 的赛场上,折戟沉沙。一年后,我从倒下的地方爬起。
我成功了。我不再是以前的那个我了。
所有的支配关系构成一颗树,一个点的受支配集 \(D_u\) 就是 \(u\) 的所有祖先。
先 \(\mathcal{O}(nm)\) 暴力把这棵树建出来。一个假做法是加边直接在支配树上加边,可惜是假的。
对于一条 \(u \to v\) 的边,找到支配树上的 \(\text{LCA}\),然后找到 \(v\) 上深度为 \(\text{LCA}+1\) 的祖先,查询这个点的支配集,改变的量就是答案。
为什么?
首先,这个子树以外,都是不会变的。
否则,如果要变,那么思考一下求支配集的过程,那么他的父亲会变成 \(\text{LCA}\)。
然后就做完了,时间复杂度 \(\mathcal{O}(m(n+q))\)。代码实现。

浙公网安备 33010602011771号