2023.11.11 总结
T1
题意:给出一个网格图,边无向,从 \((1,1)\) 走到 $ (n,m) $ ,横着的边开始能通过,竖着的边开始不能通过,有 \(k\) 个点可以在上面将所有边是否能通过给反过来,通过 \(1\) 条边需要 \(1\) 代价,翻转也需要 \(1\) 代价,求最小代价,若不能到达输出 \(-1\) ,\(n,m,k \le 10^6\)。
我们可以做分层图最短路,分两层,表示只能横着走或只能竖着走,层与层之间转移代价为 \(1\) 。
将一层内同一行或同一列的能翻转的点穿起来,就建完图了。
做堆优化 \(dijkstra\) 即可,时间复杂度 \(O(klogk)\) 。
T2
题意:给出一个长度为 \(n\) 的序列 \(a\) ,让你求所有递增子序列的异或和出现过哪些数,\(n \le 10^6,a_i \le 5000\)。
可很快想到一个暴力,开 \(vector f[...]\) ,\(f_i\) 表示结尾为 \(i\) 时出现过什么数。
每次向上推移即可,时间复杂度 \(O(nm^2)\) ,\(m\) 为 \(a_i\) 异或能到的最大值,即为 \(2^{13}=8192\) 。
考虑优化,我们可以在每一次上推完后将 \(f_i\) 清空掉,因为下一次上推旧的必定没贡献。
我们还需避免在同一个 \(vector\) 里面放同样的数,对此,我们可以开一个数组 \(d\) 初始值设为 \(m\) ,
表示在数 \(i\) 在 $d_i $ 至 $ m$ 里面全部都放过。
每次只需放到当前 \(a_i\) 到最大的仍为放过的位置即可,之后将 \(d_i\) 设为 \(a_i\) 。
时间复杂度 \(O(m^2)\)
T3
见此篇题解
T4
跳过