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 { 16 puts(f(1, 1) <= f(n, n) ? "White" : "Black"); 17 } 18 return 0; 19 }View Code
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; 9 }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 }View Code
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