USACO 22JAN
赛时爆炸了,很多平常熟悉的套路都没想起来,但题目还是要补的不是吗?
T1¶
题意:给一个长度为 \(N\) 的数组 \(a\) ,若相邻两数之差的绝对值不超过 \(K\) 则可以交换,问能得到的所有 \(a\) 中字典序最小的一个。
数据范围:\(1\le N,K\le 10^5,1\le a_i\le 10^9\)
发现 \(|a_i-a_j| > K\) 的数无法交换,于是找到所有这样的限制做拓扑排序。如何做?正常最小拓扑序是把所有入度为0的点放入优先队列中,然后每次取堆顶的点并从图中删除。时间复杂度为 \(O(NK)\) 。
思考一下如何优化,首先可以对原数组离散化,用一个线段树来维护当前可能的最小位置,每次取出作为答案并更新与其有连边的点的入度即可。具体地,若当前点的权值为 \(u\) ,则 \([1,m]\setminus[u-K+1,u+K-1]\) 中的所有权值对应的点的入度 \(-1\) 。需要一个带懒标记线段树做区间更新。
时间复杂度:\(O(N\log N)\)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
|
T2¶
题意:给一个长度为 \(N\) 的数组 \(a\) ,相邻两项若差不大于1则可以交换,问能得到的不同 \(a\) 个数,答案模 \(10^9+7\) 。
数据范围:\(1\le N\le 5000,1\le a_i\le10^9\)
计数问题基本就是 dp 了。发现从上一题中的不大于 \(K\) 变成了不大于 \(1\) ,必然有猫腻。由于差大于 \(1\) 的数很多,所以大部分数之间是不能够对换位置的,考虑从这一点入手解决问题。
然后此时如果观察到了奇数之间不可能调换位置(除非两数相同,但是这样的调换没有意义),偶数也同理。于是设计 dp 状态为 \(dp[i][j]\) 表示当前确定了前 \(i+j\) 个位置,有 \(i\) 个奇数,\(j\) 个偶数。对每个数,预处理它最远能与它不同奇偶性的哪个数交换即可。转移是简单的。
时间复杂度:\(O(N^2)\) 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
|
T3¶
题意:给定 \(n\) 组向量,求每一组中选出一个向量,加起来后最大的长度。
数据范围:向量数不超过 \(10^5\) ,\(|x|,|y|\le \frac{10^9}{N}\) 。
我们维护当前所有可能答案构成的点集,有
性质1:如果一个点不在该点集的凸包上,那么这个点离原点的距离不是最大的。
对每一组向量我们都可以求出它的凸包。对于第 \(i\) 组向量,我们将它的凸包与前 \(i-1\) 组得到的答案凸包合并,用 Minkowski 和即可。
时间复杂度:\(O(N\log N)\) 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
|
赛后总结:
这次比赛对时间的把控极为失败,不应该因为看到了熟悉/感觉能做的题目就一直死磕在上面,这对比赛是极其不利的,希望以后能学会合理利用时间。除了T3的计算几何对USACO是相对新颖的考点,另外两题并没有什么新的东西,T3也容易在了解一点知识后套模板解决。