Codeforces Round #575 (Div. 3)

A - Three Piles of Candies

题意:三堆糖果两人各取一堆,第三堆两人分,最后两人中糖果多的丢弃部分糖果,使得两人糖果数相同。

分析:一人拿最少的,另一人拿次少的,然后两人分最多的使得两人总数相差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 }
View Code

B - Odd Sum Segments

题意:将一个数组分为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 }
View Code

方法二:找到数组内的所有奇数位置和数量。若有偶数个奇数,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 }
View Code

C - Robot Breakout

题意: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 }
View Code

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 }
View Code

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 }
View Code

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 }
View Code

F - K-th Path

题意:给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 }
View Code

(如有问题,请在评论区和我说)

原文地址:https://www.cnblogs.com/F-Mu/p/11261677.html