Lyft Level 5 Challenge 2018 - Final Round (Open Div. 2)
A. The King‘s Race
簽.
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define ll long long 5 ll n, x, y; 6 7 ll f(ll a, ll b) 8 { 9 return max(abs(a - x), abs(b - y)); 10 } 11 12 int main() 13 { 14 while (scanf("%lld%lld%lld", &n, &x, &y) != EOF) 15 {View Code16 puts(f(1, 1) <= f(n, n) ? "White" : "Black"); 17 } 18 return 0; 19 }
B. Taxi drivers and Lyft
簽.
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define N 100010 5 int n, m; 6 struct node 7 { 8 int x, t, id, small, big, small_pos, big_pos; 9View Code}a[N << 1]; 10 int ans[N]; 11 12 int main() 13 { 14 while (scanf("%d%d", &n, &m) != EOF) 15 { 16 memset(ans, 0, sizeof ans); 17 for (int i = 1, x; i <= n + m; ++i) 18 { 19 scanf("%d", &x); 20 a[i].x = x; 21 } 22 for(int i = 1, tmp = 0, t; i <= n + m; ++i) 23 { 24 scanf("%d", &t); 25 a[i].t = t; 26 if (t == 1) 27 a[i].id = ++tmp; 28 } 29 int Max = -((int)1e9 + 1), pos = -1; 30 for (int i = 1; i <= n + m; ++i) 31 { 32 if (a[i].t == 1) 33 { 34 Max = a[i].x; 35 pos = a[i].id; 36 } 37 else 38 { 39 a[i].small = Max; 40 a[i].small_pos = pos; 41 } 42 } 43 int Min = (int)2e9 + 1; pos = -1; 44 for (int i = n + m; i >= 1; --i) 45 { 46 if (a[i].t == 1) 47 { 48 Min = a[i].x; 49 pos = a[i].id; 50 } 51 else 52 { 53 a[i].big = Min; 54 a[i].big_pos = pos; 55 } 56 } 57 for (int i = 1; i <= n + m; ++i) if (a[i].t == 0) 58 { 59 int A = abs(a[i].x - a[i].small), B = abs(a[i].x - a[i].big); 60 if (A <= B) ++ans[a[i].small_pos]; 61 else ++ans[a[i].big_pos]; 62 } 63 for (int i = 1; i <= m; ++i) 64 printf("%d%c", ans[i], " \n"[i == m]); 65 } 66 return 0; 67 }
C. The Tower is Going Home
Solved.
題意:
要從$(1, 1) 走到(1e9, *)$
$有一些橫著和豎著的欄桿擋著,每次只能移動到曼哈頓距離為1的格子$
$求最小的需要去掉的欄桿的數量,使得可以到達目的地$
思路:
考慮橫著的欄桿,$如果左端點不是1,那麽該欄桿沒有用$
$那麽考慮從左到右掃一遍,豎著的欄桿按順序去掉後$
$右端點沒有超過該豎著欄桿的橫欄桿,該橫欄桿也沒有用$
更新答案即可
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define N 100010 5 int n, m, q; 6 int a[N], b[N]; 7 8 9 int main() 10 { 11 while (scanf("%d%d", &n, &m) != EOF) 12 { 13 for (int i = 1; i <= n; ++i) scanf("%d", a + i); 14 sort(a + 1, a + 1 + n); 15 q = 0; 16 for (int i = 1, x1, x2, y; i <= m; ++i) 17 { 18 scanf("%d%d%d", &x1, &x2, &y); 19 if (x1 == 1) b[++q] = x2; 20 } 21 sort(b + 1, b + 1 + q); 22 int res = q; 23 int pos = 0; 24 a[n + 1] = (int)1e9; 25 for (int i = 0; i <= n; ++i) 26 { 27 while (pos < q && b[pos + 1] < a[i + 1]) ++pos; 28 res = min(res, i + q - pos); 29 } 30 printf("%d\n", res); 31 } 32 return 0; 33 }View Code
D. Intersecting Subtrees
Upsolved.
題意:
有一棵樹,$A選了一棵子樹,B選了一棵子樹$
$但是B對樹的標號和A對樹的標號不同$
$現在告訴你以A標號的樹的形態$
$以及A, B各自選擇的子樹的標號$
$有5次詢問機會,每次可以詢問$
$A \; x\;\; 返回B對應的標號$
$B \; y \;\; 返回A對應的標號$
最後給出答案,$A, B選擇的子樹是否有交,有的話輸出其中一個交點,否則輸出-1$
思路:
隨便選一個$B中的點,得到A中的點,如果剛好是A子樹內的,直接輸出$
$否則以這個點去找一個最近的點,再詢問一次,如果是就輸出,否則就是-1$
$因為找到的是最近的屬於A選擇子樹內的點,說明這條路徑上沒有交,如果這個點不是交$
$那麽說明那個點那頭也不會有交$
$如果有交的話,這個點就會把B選擇的子樹分成兩部分,就不是連通的,和題意想違背$
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define N 1010 5 int t, n, k, st; 6 int visa[N], visb[N]; 7 vector <int> G[N]; 8 9 int fa[N]; 10 void BFS(int S) 11 { 12 queue <int> q; q.push(S); fa[st] = S; 13 while (!q.empty()) 14 { 15 int u = q.front(); q.pop(); 16 if (visa[u]) 17 { 18 st = u; 19 return; 20 } 21 for (auto v : G[u]) if (v != fa[u]) 22 { 23 fa[v] = u; 24 q.push(v); 25 } 26 } 27 } 28 29 int dfs(int num,int fa){ 30 if(visa[num]){ 31 return num; 32 } 33 for (auto v : G[num]) if (v != fa) 34 { 35 int temp=dfs(v,num); 36 if(temp!=-1){ 37 return temp; 38 } 39 } 40 return -1; 41 } 42 43 int main() 44 { 45 scanf("%d", &t); 46 while (t--) 47 { 48 scanf("%d", &n); 49 for (int i = 1; i <= n; ++i) G[i].clear(); 50 memset(visa, 0, sizeof visa); 51 memset(visb, 0, sizeof visb); 52 for (int i = 1, u, v; i < n; ++i) 53 { 54 scanf("%d%d", &u, &v); 55 G[u].push_back(v); 56 G[v].push_back(u); 57 } 58 scanf("%d", &k); 59 for (int i = 1, x; i <= k; ++i) 60 { 61 scanf("%d", &x); 62 visa[x] = 1; 63 } 64 scanf("%d", &k); 65 for (int i = 1, x; i <= k; ++i) 66 { 67 scanf("%d", &x); 68 visb[x] = 1; 69 st = x; 70 } 71 printf("B %d\n", st); 72 fflush(stdout); 73 st = -1; 74 scanf("%d", &st); 75 if (visa[st]) 76 { 77 printf("C %d\n", st); 78 fflush(stdout); 79 continue; 80 } 81 BFS(st); 82 //st = dfs(st, st); 83 int ed; 84 printf("A %d\n", st); 85 fflush(stdout); 86 scanf("%d", &ed); 87 if (visa[st] && visb[ed]) 88 printf("C %d\n", st); 89 else 90 puts("C -1"); 91 fflush(stdout); 92 } 93 return 0; 94 }View Code
E. Optimal Polygon Perimeter
Upsolved.
題意:
給出一個凸包,兩點之間的距離為曼哈頓距離
定義$f(x) 為選擇x個點構成一個凸包的最大周長$
輸出$f(3), f(4) \cdots f(n)$
思路:
對於$n >= 4的答案,就是選擇最大上界,最大下界,最大左界,最大右界,構成的矩形的周長$
$再考慮n == 3的時候$
$因為是一個三角形,那麽肯定是某兩個最構成的兩個點,再加上一個點,那個點枚舉求解即可$
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define N 300010 5 int n; 6 int x[N], y[N]; 7 8 int main() 9 { 10 while (scanf("%d", &n) != EOF) 11 { 12 int Max[2], Min[2]; 13 Min[0] = Min[1] = (int)1e9; 14 Max[0] = Max[1] = -(int)1e9; 15 for (int i = 1; i <= n; ++i) 16 { 17 scanf("%d%d", x + i, y + i); 18 Max[0] = max(Max[0], x[i]); 19 Min[0] = min(Min[0], x[i]); 20 Max[1] = max(Max[1], y[i]); 21 Min[1] = min(Min[1], y[i]); 22 } 23 if (n == 3) 24 printf("%d\n", 2 * (Max[0] + Max[1] - Min[0] - Min[1])); 25 else 26 { 27 int res = 0; 28 for (int i = 1; i <= n; ++i) 29 res = max(res, max(abs(x[i] - Max[0]), abs(x[i] - Min[0])) + max(abs(y[i] - Max[1]), abs(y[i] - Min[1]))); 30 res *= 2; 31 printf("%d", res); 32 for (int i = 4; i <= n; ++i) 33 printf(" %d", 2 * (Max[0] + Max[1] - Min[0] - Min[1])); 34 puts(""); 35 } 36 } 37 return 0; 38 }View Code
Lyft Level 5 Challenge 2018 - Final Round (Open Div. 2)