zoukankan      html  css  js  c++  java
  • 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

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

  • 相关阅读:
    29 求和
    28 跳转控制语句 goto
    27 跳转控制语句 continue
    26 跳转控制语句 break
    25 打印金字塔
    24 打印九九乘法表
    23 多重循环控制
    22 do-while 循环
    21 while 循环
    20 for循环控制
  • 原文地址:https://www.cnblogs.com/F-Mu/p/11261677.html
Copyright © 2011-2022 走看看