Codeforces Round #575 (Div. 3)
题意:三堆糖果两人各取一堆,第三堆两人分,最后两人中糖果多的丢弃部分糖果,使得两人糖果数相同。
分析:一人拿最少的,另一人拿次少的,然后两人分最多的使得两人总数相差0或者1。
1 #include <bits/stdc++.h> 2 3 #define maxn 100005 4 #define mod 1000000007 5 #define inf 0x3f3f3f3f 6 #define start ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); 7 #define ll long long 8 using namespace std; 9 10 int main() { 11 start; 12 int T; 13 cin >> T; 14 while (T--) { 15 ll a, b, c; 16 cin >> a >> b >> c; 17 cout << (a + b + c) / 2 << endl; 18 } 19 return 0; 20 }
题意:将一个数组分为k段,每一段和都为奇数。
分析:方法一:若数组和为偶数,k为奇数,显然不行;若数组和为奇数,k为偶数,显然不行。然后找前面k-1段为奇数的子数组,k=1时特判(特判写差了wa了几次)。
1 #include <bits/stdc++.h> 2 3 #define maxn 200005 4 #define mod 1000000007 5 #define inf 0x3f3f3f3f 6 #define start ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); 7 #define ll long long 8 using namespace std; 9 int a[maxn]; 10 11 int main() { 12 start; 13 int T; 14 cin >> T; 15 while (T--) { 16 int n, k; 17 cin >> n >> k; 18 ll sum = 0; 19 for (int i = 1; i <= n; ++i) { 20 cin >> a[i]; 21 sum += a[i]; 22 } 23 bool flag = true; 24 if ((k & 1) && (!(sum & 1))) 25 flag = false; 26 if ((!(k & 1)) && (sum & 1)) 27 flag = false; 28 if (!flag) { 29 cout << "NO" << endl; 30 continue; 31 } 32 if (k == 1) { 33 if (sum & 1) { 34 cout << "YES" << endl; 35 cout << n << endl; 36 continue; 37 } else 38 cout << "NO" << endl; 39 } 40 ll t = 0; 41 int ans = 0; 42 vector<int> v; 43 for (int i = 1; i <= n; ++i) { 44 t += a[i]; 45 if (t & 1) { 46 v.push_back(i); 47 t = 0; 48 ++ans; 49 if (ans == k - 1) 50 break; 51 } 52 } 53 if (ans != k - 1) { 54 cout << "NO" << endl; 55 continue; 56 } 57 cout << "YES" << endl; 58 for (auto i:v) 59 cout << i << ' '; 60 cout << n << endl; 61 } 62 return 0; 63 }
方法二:找到数组内的所有奇数位置和数量。若有偶数个奇数,k为奇数,显然不行;若有奇数个奇数,k为偶数,显然不行;若奇数个数小于k,显然不行。将前k-1个奇数位置输出并将n输出即可。这样构造,前k-1段每个只有一个奇数,将其余奇数归于最后一段。
1 #include <bits/stdc++.h> 2 3 #define maxn 200005 4 #define mod 1000000007 5 #define inf 0x3f3f3f3f 6 #define start ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); 7 #define ll long long 8 using namespace std; 9 int a[maxn]; 10 11 int main() { 12 start; 13 int T; 14 cin >> T; 15 while (T--) { 16 vector<int> v; 17 int n, k; 18 cin >> n >> k; 19 int t = 0; 20 for (int i = 1; i <= n; ++i) { 21 cin >> a[i]; 22 if (a[i] & 1) { 23 ++t; 24 v.push_back(i); 25 } 26 } 27 if (t < k) 28 cout << "NO" << endl; 29 else { 30 int x = t - (k - 1); 31 if (x & 1) { 32 cout << "YES" << endl; 33 for (int i = 0; i < k - 1; ++i) 34 cout << v[i] << ' '; 35 cout << n << endl; 36 } else 37 cout << "NO" << endl; 38 } 39 } 40 return 0; 41 }
题意:n个机器人,每个机器人可能不能走上下左右四个方向中的某几个(0~4)方向,问是否存在一点,所有机器人都能到达。
分析:若机器人不能走左边,则将答案这点必在该机器人上下右方向,对于每个机器人进行判定,可找到四个方向所能到达的边界,是一个矩形,取其中一点即可。
1 #include <bits/stdc++.h> 2 3 #define maxn 100005 4 #define mod 1000000007 5 #define inf 0x3f3f3f3f 6 #define start ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); 7 #define ll long long 8 using namespace std; 9 const int maxt = 100000; 10 struct node { 11 int x, y; 12 int a, b, c, d; 13 } a[maxn]; 14 int shang, xia, zuo, you; 15 16 void judge(node x) { 17 if (x.a == 0) 18 zuo = max(zuo, x.x); 19 if (x.b == 0) 20 shang = min(shang, x.y); 21 if (x.c == 0) 22 you = min(you, x.x); 23 if (x.d == 0) 24 xia = max(xia, x.y); 25 } 26 27 int main() { 28 start; 29 int T; 30 cin >> T; 31 while (T--) { 32 shang = you = maxt; 33 xia = zuo = -maxt; 34 int n; 35 cin >> n; 36 for (int i = 1; i <= n; ++i) 37 cin >> a[i].x >> a[i].y >> a[i].a >> a[i].b >> a[i].c >> a[i].d; 38 for (int i = 1; i <= n; ++i) 39 judge(a[i]); 40 if (shang < xia || zuo > you) 41 cout << 0 << endl; 42 else 43 cout << 1 << ' ' << zuo << ' ' << shang << endl; 44 } 45 return 0; 46 }
D1 - RGB Substring (easy version)
题意:长度为n的串中只有'B','G','R'三个字符中的一个,在一个长度为k的子串中,改变最少的字符使得子串为"RGBRGBRGB..."的子串。
分析:数据范围不大,直接暴力,从起始位置取长度为k的子串然后模拟。每次取时第一个字符都保证不变,如果第一个字符变化,则可取原串后一个点为起点,此时两个串只差一个字符,若后者的最后一个点不变化,则改变数会更小。特判后k个字符,因为此性质不再成立。特判方法见D2。
1 #include <bits/stdc++.h> 2 3 #define maxn 200005 4 #define mod 1000000007 5 #define inf 0x3f3f3f3f 6 #define start ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); 7 #define ll long long 8 using namespace std; 9 char c[] = "RGB"; 10 11 int main() { 12 start; 13 int T; 14 cin >> T; 15 while (T--) { 16 int n, k; 17 string a; 18 cin >> n >> k >> a; 19 int an = inf; 20 for (int i = 0; i + k <= a.size(); ++i) { 21 string b; 22 b = a; 23 int ans = 0; 24 int t; 25 if (b[i] == 'R') 26 t = 0; 27 else if (b[i] == 'G') 28 t = 1; 29 else if (b[i] == 'B') 30 t = 2; 31 else 32 continue; 33 for (int j = i; j < i + k; ++j) { 34 if (b[j] != c[t]) 35 ++ans; 36 t = (t + 1) % 3; 37 } 38 an = min(an, ans); 39 } 40 string b = a.substr(a.size() - k); 41 for (int t = 0; t < 3; ++t) { 42 int ans = 0; 43 int z = t; 44 for (int i = 0; i < b.size(); ++i) { 45 if (b[i] != c[z]) 46 ++ans; 47 z = (z + 1) % 3; 48 } 49 an = min(an, ans); 50 } 51 cout << min(an, k) << endl; 52 } 53 return 0; 54 }
D2 - RGB Substring (hard version)
题意:如D1。
分析:子串是"RGBRGBRGB..."的子串有三种情况,分别以'B','G','R'开头。将原串分别变成这三种情况,对每k个字符计算变化数,滑动区间,取最小即可。
1 #include <bits/stdc++.h> 2 3 #define maxn 200005 4 #define mod 1000000007 5 #define inf 0x3f3f3f3f 6 #define start ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); 7 #define ll long long 8 using namespace std; 9 char c[] = "RGB"; 10 11 int main() { 12 start; 13 int T; 14 cin >> T; 15 while (T--) { 16 int n, k; 17 cin >> n >> k; 18 string a; 19 cin >> a; 20 int ans = k; 21 for (int t = 0; t < 3; ++t) { 22 int j = t; 23 int s = t; 24 int tmp = 0; 25 for (int i = 0; i < k; ++i) { 26 if (a[i] != c[j]) 27 ++tmp; 28 j = (j + 1) % 3; 29 } 30 ans = min(ans, tmp); 31 for (int l = 0, r = k; r < a.size(); ++l, ++r) { 32 if (a[l] != c[s]) 33 tmp--; 34 if (a[r] != c[j]) 35 tmp++; 36 s = (s + 1) % 3; 37 j = (j + 1) % 3; 38 ans = min(ans, tmp); 39 } 40 } 41 cout << ans << endl; 42 } 43 return 0; 44 }
E - Connected Component on a Chessboard
题意:国际象棋盘上取b个黑点和w个白点,这些点在棋盘上相连。
分析:不妨设黑点比白点多(若白点比黑点多放法相同)黑点在同一行每隔一个点取一个,取b个黑点,此时最多取3*b+1个白点,最少取b个白点,且由假设可知,b~3*b+1个白点都可取到。(第一时间想到了3*b+1的构造但45分钟没想清b~3*b之间的构造,反而想的很复杂,时间过了一下子就想出来了,太菜了)
1 #include <bits/stdc++.h> 2 3 #define maxn 200005 4 #define mod 1000000007 5 #define inf 0x3f3f3f3f 6 #define start ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); 7 #define ll long long 8 using namespace std; 9 10 int main() { 11 start; 12 int T; 13 cin >> T; 14 while (T--) { 15 int x, y; 16 cin >> x >> y; 17 int a = x, b = y; 18 if (a > b) 19 swap(a, b); 20 if (b > 3 * a + 1) 21 cout << "NO" << endl; 22 else { 23 cout << "YES" << endl; 24 if (x >= y) { 25 for (int i = 1; i <= y; ++i) 26 cout << 2 << ' ' << 2 * i << endl; 27 for (int i = 1; i <= y; ++i) 28 cout << 2 << ' ' << 2 * i + 1 << endl; 29 x -= y; 30 if (x == 0) 31 continue; 32 cout << 2 << ' ' << 1 << endl; 33 x--; 34 for (int i = 1; i <= x && i <= y; ++i) 35 cout << 1 << ' ' << 2 * i << endl; 36 x = max(x - y, 0); 37 for (int i = 1; i <= x; ++i) 38 cout << 3 << ' ' << 2 * i << endl; 39 } else { 40 for (int i = 1; i <= x; ++i) 41 cout << 3 << ' ' << 2 * i << endl; 42 for (int i = 1; i <= x; ++i) 43 cout << 3 << ' ' << 2 * i + 1 << endl; 44 y -= x; 45 if (y == 0) 46 continue; 47 cout << 3 << ' ' << 1 << endl; 48 y--; 49 for (int i = 1; i <= x && i <= y; ++i) 50 cout << 2 << ' ' << 2 * i << endl; 51 y = max(y - x, 0); 52 for (int i = 1; i <= y; ++i) 53 cout << 4 << ' ' << 2 * i << endl; 54 } 55 } 56 } 57 return 0; 58 }
题意:给n个点,m条边,这张图中两个点间第k小的距离。
分析:k<=400,想到了Floyd但不知道怎么施行,后来看了看别人的题解(https://blog.csdn.net/qq_40791842/article/details/97315009)恍然大悟。将前k条边的点构成的子图构造出来,第k+1条边已然出局。然后将这最多2*k个节点(最多800个点)进行离散化(离散化代码出自卿学姐(B站账号:qscqesze)),然后使用Floyd即可。
1 #include <bits/stdc++.h> 2 3 #define maxn 200005 4 #define mod 1000000007 5 #define inf 0x3f3f3f3f3f3f3f3f 6 #define start ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); 7 #define ll long long 8 using namespace std; 9 ll dis[1005][1005]; 10 11 struct node { 12 int u, v; 13 ll w; 14 15 bool operator<(const node &b) { 16 return w < b.w; 17 } 18 } a[maxn]; 19 20 vector<int> v; 21 22 int main() { 23 start; 24 int n, m, k; 25 cin >> n >> m >> k; 26 for (int i = 1; i <= m; ++i) 27 cin >> a[i].u >> a[i].v >> a[i].w; 28 sort(a + 1, a + m + 1); 29 for (int i = 1; i <= min(k, m); ++i) 30 v.push_back(a[i].u), v.push_back(a[i].v); 31 sort(v.begin(), v.end()); 32 v.erase(unique(v.begin(), v.end()), v.end()); 33 memset(dis, 0x3f, sizeof(dis)); 34 for (int i = 1; i <= min(k, m); ++i) { 35 int from = lower_bound(v.begin(), v.end(), a[i].u) - v.begin(); 36 int to = lower_bound(v.begin(), v.end(), a[i].v) - v.begin(); 37 dis[from][to] = dis[to][from] = min(dis[from][to], a[i].w); 38 } 39 for (int t = 0; t < v.size(); ++t) 40 for (int i = 0; i < v.size(); ++i) 41 for (int j = 0; j < v.size(); ++j) 42 dis[i][j] = min(dis[i][j], dis[i][t] + dis[t][j]); 43 vector<ll> vv; 44 for (int i = 0; i < v.size(); ++i) 45 for (int j = i + 1; j < v.size(); ++j) 46 vv.push_back(dis[i][j]); 47 sort(vv.begin(), vv.end()); 48 cout << vv[k - 1] << endl; 49 return 0; 50 }
(如有问题,请在评论区和我说)