题目大意
题目描述
在一个圆上有 N N N 只蚂蚁。圆被顺时针划分为 L L L 个位置,编号为 1 1 1 到 L L L ,其中位置 L L L 与位置 1 1 1 相邻。
每只蚂蚁初始站在不同的位置上,并且都需要到达各自不同的目标位置。
在每一秒内,每只蚂蚁可以选择:
在任何时刻(包括在两个位置之间移动的过程中),任意两只蚂蚁都不能处于同一个位置。例如,如果某只蚂蚁在某一秒内顺时针从位置 1 1 1 移动到位置 2 2 2 ,那么在同一秒内,其他蚂蚁不能进行以下操作:
停留在位置 2 2 2 (这会导致两只蚂蚁在位置 2 2 2 相遇)。
逆时针从位置 3 3 3 移动到位置 2 2 2 (这会导致两只蚂蚁在位置 2 2 2 相遇)。
逆时针从位置 2 2 2 移动到位置 1 1 1 (这会导致两只蚂蚁在位置 1 1 1 和位置 2 2 2 之间相遇)。
你需要判断是否有可能让所有蚂蚁都到达各自的目标位置。如果可以,求出所需的最短时间(秒数)。
输入格式
第一行包含两个整数 N N N (1 ≤ N ≤ 1000 1 \le N \le 1000 1 ≤ N ≤ 1 0 0 0 )和 L L L (1 ≤ L ≤ 1 0 9 1 \le L \le 10^9 1 ≤ L ≤ 1 0 9 ),分别表示蚂蚁的数量和位置的总数。
第二行包含 N N N 个互不相同的整数 A 1 , A 2 , … , A N A_1, A_2, \dots, A_N A 1 , A 2 , … , A N (1 ≤ A i ≤ L 1 \le A_i \le L 1 ≤ A i ≤ L ),表示每只蚂蚁的初始位置。
第三行包含 N N N 个互不相同的整数 B 1 , B 2 , … , B N B_1, B_2, \dots, B_N B 1 , B 2 , … , B N (1 ≤ B i ≤ L 1 \le B_i \le L 1 ≤ B i ≤ L ),表示每只蚂蚁的目标位置。
输出格式
输出一行,包含一个整数,表示所有蚂蚁到达目标位置所需的最短时间。如果无论如何都无法全部到达目标位置,则输出星号 *。
样例展示与解释
样例 1
输入:
输出:
样例 1 解释 :两只蚂蚁初始就已经在各自的目标位置上,因此需要 0 0 0 秒。
样例 2
输入:
输出:
样例 2 解释 :两只蚂蚁可以同时顺时针(或同时逆时针)移动,仅需 1 1 1 秒即可到达目标位置。
样例 3
输入:
输出:
样例 4
输入:
输出:
样例 5
输入:
输出:
样例 5 解释 :三只蚂蚁都可以选择逆时针移动,其中第二只蚂蚁需要在中途停留一秒。
思路讲解
这道题目,实际上可以 O ( n ) O(n) O ( n ) 解决(忽略了快排的时间复杂度),至少我们的做法是这个时间复杂度的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 sort (all (lr_global));for (int i = 0 ; i < SZ (lr_global); ++i) { if (lr_global[0 ].r > lr_global[i].r) { lr_global[i].r += L; } } auto check = [&]() -> bool { for (int i = 1 ; i < N; ++i) { if (lr_global[i].l == lr_global[i - 1 ].l) { return false ; } } for (int i = 1 ; i < N; ++i) { if (lr_global[i].r <= lr_global[i - 1 ].r) { return false ; } } return true ; }; if (!check ()) { cout << "*\n" ; return ; }
核心代码就这一段,只能说化曲为直 yyds。
1 2 3 4 5 6 7 for (ll shift: {-1 , 0 , 1 }) { ll ans = 0 ; for (auto [l,r]: lr_global) { ans = max (abs (l + L * shift - r), ans); } ans_global = min (ans_global, ans); }
为什么这个代码对呢?其实在化曲为直下,一切都非常简单。
说白了,我们只要 l 的相对位置不变,r 的相对位置不变,那么就一定有解,是不是?
那么,我们知道,一个点,他切换方向,其实就是 l 在化曲为直的线段上,平移了 Len 位 。如果其他点不也平移的 L 位的话 ,这个一定会导致错误的发生(即 l 的相对位置发生变化 )!
那么我们就知道了,要切换方向,要么一起切换,要么一起不切换 。
当然,你会说,这很奇怪啊,明明这个有些例子是有些点逆时针,有些点顺时针啊?其实,这个是因为为了符合我们的第一个条件,就是起始点和结束点必须都保持升序的条件,在保持这个条件的情况下,其实方向的变化是一起的。
AC代码
AC
http://codeforces.com/gym/106416/submission/368041079
源代码
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 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 #include <bits/stdc++.h> #define all(vec) vec.begin(),vec.end() #define lson(o) (o<<1) #define rson(o) (o<<1|1) #define SZ(a) ((long long) a.size()) #define debug(var) cerr << #var <<" = [" <<var<<"]" <<"\n" ; #define debug1d(a) \ cerr << #a << " = [" ; \ for (int i = 0; i < (int)(a).size(); i++) \ cerr << (i ? ", " : "" ) << a[i]; \ cerr << "]\n" ; #define debug2d(a) \ cerr << #a << " = [\n" ; \ for (int i = 0; i < (int)(a).size(); i++) \ { \ cerr << " [" ; \ for (int j = 0; j < (int)(a[i]).size(); j++) \ cerr << (j ? ", " : "" ) << a[i][j]; \ cerr << "]\n" ; \ } \ cerr << "]\n" ; #define cend cerr<<"\n-----------\n" #define fsp(x) fixed<<setprecision(x) using namespace std;using ll = long long ;using ull = unsigned long long ;using DB = double ;using i128 = __int128;using CD = complex<double >;static constexpr ll MAXN = (ll) 1e6 + 10 , INF = (1ll << 61 ) - 1 ;static constexpr ll mod = 998244353 ; static constexpr double eps = 1e-8 ;const double PI = acos (-1.0 );ll lT, testcase; struct L_R { ll l, r; bool operator <(const L_R &o) const { return l < o.l; } }; void Solve () { ll N, L; cin >> N >> L; vector<L_R> lr_global (N) ; for (int i = 0 ; i < N; ++i) cin >> lr_global[i].l; for (int i = 0 ; i < N; ++i) cin >> lr_global[i].r; sort (all (lr_global)); for (int i = 0 ; i < SZ (lr_global); ++i) { if (lr_global[0 ].r > lr_global[i].r) { lr_global[i].r += L; } } auto check = [&]() -> bool { for (int i = 1 ; i < N; ++i) { if (lr_global[i].l == lr_global[i - 1 ].l) { return false ; } } for (int i = 1 ; i < N; ++i) { if (lr_global[i].r <= lr_global[i - 1 ].r) { return false ; } } return true ; }; if (!check ()) { cout << "*\n" ; return ; } ll ans_global = INF; for (ll shift: {-1 , 0 , 1 }) { ll ans = 0 ; for (auto [l,r]: lr_global) { ans = max (abs (l + L * shift - r), ans); } ans_global = min (ans_global, ans); } cout << ans_global << "\n" ; } signed main () { ios::sync_with_stdio (false ); cin.tie (nullptr ); cout.tie (nullptr ); #ifdef LOCAL cout.setf (ios::unitbuf); #endif Solve (); return 0 ; }
心路历程(WA,TLE,MLE……)