zoukankan      html  css  js  c++  java
  • CF Round #575 Div3

    # CF Round #575 Div3
    ## A. Three Piles of Candies
    题意:Alice 和 Bob 两个人分糖果, 给你三堆糖果, 每人选择一堆, 剩下一堆分配使得两人的糖果数量一样多, 问两人最后糖果数最多可能是多少

    思路:两个人选择糖果数少的两堆, 分最多的那一堆,最后两人最多可能分到的就是三堆糖果总数的一半

    //
    // Created by mile on 2019/7/24.
    //
    
    #include <bits/stdc++.h>
    
    #define maxn 10005
    #define ps push
    #define pb push_back
    using namespace std;
    typedef long long LL;
    
    
    int main()
    {
        int q;
        cin>>q;
        while(q--) {
            LL a, b, c;
            cin>>a>>b>>c;
            cout<<(a+b+c)/2<<endl;
        }
        return 0;
    }
    View Code
     
    ## B Odd Sum Segments
    题意:给定一个长度为n的数组和一个数字k,将数组截成k个子数组,要求每个子数组的和为奇数。
    如果可以输出"YES",以及每一个子数组的最后一个数在原数组的下标,否则输出"NO"。
     
    思路:两数相加满足:奇数 + 奇数 = 偶数, 奇数 + 偶数 = 奇数, 偶数 + 偶数 = 偶数, 那么题目所说的子数组至少有一个奇数且奇数的个数为奇数。
     
    得出结论: 1. 原数组中奇数小于k无答案 2.在前k-1个奇数后分割数组,前k-1个子数组中只有一个奇数,sum必为奇数,检查最后一个子数组的sum, 如果为奇数就存在答案,否则无答案。
     
    //
    // Created by mile on 2019/7/24.
    //
    
    #include <bits/stdc++.h>
    
    using namespace std;
    
    long long num[200005], id[200005];
    
    int main()
    {
        int q;
        scanf("%d", &q);
        while(q--) {
            int n, k;
            scanf("%d%d", &n, &k);
            int s = 0;
            for(int i = 1; i <= n; i++) {
                scanf("%lld", &num[i]);
                if(num[i]%2 == 1) s++;
            }
            if(s < k) puts("NO");
            else {
                int cnt = 1;
                long long sum = 0;
                for(int i = 1; i<= n; i++) {
                    sum += num[i];
                    if(sum%2 == 1 && k > 1) id[cnt++] = i, k--, sum = 0;
                }
                sum = 0;
                for(int i = id[cnt-1]+1; i <= n; i++) sum += num[i];
                if(sum % 2 == 1) {
                    puts("YES");
                    id[cnt] = n;
                    for(int i = 1; i <= cnt; i++) {
                        printf("%d ", id[i]);
                    }
                    puts("");
                }
                else {
                    puts("NO");
                }
            }
        }
        return 0;
    }
    View Code
    ## C Robot Breakout
    题意:在一个x-y坐标系上有n个robots,坐标(xi, yi),每个robot有四个功能,分别为向左,向上,向右,向下移动,但是有的robot这四个功能里面某几种坏了,为你能够找到一个坐标使得每个robot都可以达到
    思路:对于完好的robot可以到达任意一点, 可以忽略。对于某个功能坏掉的robot可以得到最终坐标的一个限制,例如一个向左功能坏掉的robot,它的x坐标就是最终答案x在最小值的一个限制,因为它无法达到更左端的位置,因此对根据每个robot的坏掉的功能不断更新最终答案x和y的范围,如果得到最终minx>maxx || miny>maxy, 说明没有答案, 否则输出范围内任一点即可。
     
    //
    // Created by mile on 2019/7/24.
    //
    
    #include <bits/stdc++.h>
    
    using namespace std;
    
    int main()
    {
        int q;
        scanf("%d", &q);
        while(q--) {
            int x1 = -100000, y1 = -100000;
            int x2= 100000, y2 = 100000;
            int n;
            scanf("%d", &n);
            for(int i = 1; i <= n; i++) {
                int x, y, a, b, c, d;
                scanf("%d%d%d%d%d%d", &x, &y, &a, &b, &c, &d);
                if(a == 0) x1 = max(x1, x);
                if(b == 0) y2 = min(y2, y);
                if(c == 0) x2 = min(x2, x);
                if(d == 0) y1 = max(y1, y);
            }
            if(x1 <= x2 && y1 <= y2) {
                printf("1 %d %d
    ", x1, y1);
            }
            else puts("0");
        }
        return 0;
    }
    View Code
    ## D1. RGB Substring(easy version)
    题意:给定一个长度为n的由R、G、B三个字母组成的字符串,找到一个长度为k的区间,使得这个区间的字符串是"RGBRGBRGBRGBRGB...."这个无限字符串的一个子串,你可以修改任一个字母变成其他两个字母,来制造出题目要求的区间,问最少修改几个字母可以达到要求。多组测试
    思路:1.暴力模拟
    2.我们假设将整个字符串都变为合法字符串,利用前缀和思想,记录一个数组S, si表示要将i之前的字符串变为合法需要修改几个字母,然后对于每个i>k时,s[i]-s[i-k]就是将i-k到i这段长度为k的字符串变为合法的最小改变次数。除此之外,将整个字符串变为合法有三种情况,分别是"RGBRGB...","GBRGBRGB...","BRGBRGB...",对每种情况分别统计一次即可。
     1 //
     2 // Created by mile on 2019/7/24.
     3 //
     4  
     5 #include <bits/stdc++.h>
     6  
     7 using namespace std;
     8  
     9 int q, n, k;
    10 char str[] = "RGB";
    11 char ch[200005];
    12 int acc[200005];
    13  
    14 int Get(int x) {
    15     for(int i = 1; i <= n; i++) {
    16         acc[i] = acc[i-1] + (str[x] != ch[i]);
    17         x = (x+1)%3;
    18     }
    19     int res = acc[k];
    20     for(int i = k+1; i <= n; i++) {
    21         res = min(res, acc[i] - acc[i-k]);
    22     }
    23     return res;
    24 }
    25  
    26 int main()
    27 {
    28     scanf("%d", &q);
    29     while(q--) {
    30         scanf("%d%d", &n, &k);
    31         scanf("%s", ch+1);
    32         int res = min(min(Get(0), Get(1)), Get(2));
    33         printf("%d
    ", res);
    34     }
    35     return 0;
    36 }
    View Code
    ## D2. RGB Substring(hard version)
    题意:如D1
    思路:如D1思路2
     1 //
     2 // Created by mile on 2019/7/24.
     3 //
     4  
     5 #include <bits/stdc++.h>
     6  
     7 using namespace std;
     8  
     9 int q, n, k;
    10 char str[] = "RGB";
    11 char ch[200005];
    12 int acc[200005];
    13  
    14 int Get(int x) {
    15     for(int i = 1; i <= n; i++) {
    16         acc[i] = acc[i-1] + (str[x] != ch[i]);
    17         x = (x+1)%3;
    18     }
    19     int res = acc[k];
    20     for(int i = k+1; i <= n; i++) {
    21         res = min(res, acc[i] - acc[i-k]);
    22     }
    23     return res;
    24 }
    25  
    26 int main()
    27 {
    28     scanf("%d", &q);
    29     while(q--) {
    30         scanf("%d%d", &n, &k);
    31         scanf("%s", ch+1);
    32         int res = min(min(Get(0), Get(1)), Get(2));
    33         printf("%d
    ", res);
    34     }
    35     return 0;
    36 }
    View Code
    ## E Connected Component on a Chessboard
    题意:给定两个数b,w,在国际象棋棋盘上,找到一个联通的区域(两个方格必须有有一条公共边才算联通),使得区域里有b个黑块和w个白块。
    思路:国际象棋棋盘黑白块相间分布,b和w中大的那个不能大于小的那个三倍加一,先根据白块和黑块中少的那个选择一排,首先多的可以放在少的后面一个, 然后可以放在少的上一排相同位置,最后是少的第一块前面和下一排的相同位置。初始位置可以任选,棋盘范围很大,1到1e9-1e5之间都可以。
     1 //
     2 // Created by mile on 2019/7/24.
     3 //
     4  
     5 #include <bits/stdc++.h>
     6  
     7 #define pb push_back
     8 #define mp make_pair
     9 using namespace std;
    10  
    11 vector<pair<int, int> > ans;
    12  
    13 int main()
    14 {
    15     int q;
    16     scanf("%d", &q);
    17     while(q--) {
    18         int b, w;
    19         int x, y;
    20         x = y = 1000000;
    21         scanf("%d%d", &b, &w);
    22         if(b < w) swap(b, w), x++;
    23         for(int i = 0; i < w; i++) {
    24             ans.pb(mp(x+i*2, y));
    25             if(b) {
    26                 ans.pb(mp(x+i*2+1, y));
    27                 b--;
    28             }
    29         }
    30         for(int i = 0; i < w; i++) {
    31             if(b) {
    32                 ans.pb(mp(x+i*2,y+1)); b--;
    33             }
    34             if(b) {
    35                 ans.pb(mp(x+i*2, y-1)); b--;
    36             }
    37         }
    38         if(b) ans.pb(mp(x-1, y)), b--;
    39         //if(b) ans.pb(mp(x+2*w-1, y)), b--;
    40         if(b != 0) {
    41             puts("NO");
    42         } else {
    43             puts("YES");
    44             for(auto it : ans) {
    45                 printf("%d %d
    ", it.first, it.second);
    46             }
    47         }
    48         ans.clear();
    49     }
    50     return 0;
    51 }
    View Code
    ## F K-th Path
    题意:给定一个无向连通图,n个点以及m条边的长度,d(i,j)表示点i到j的最短路长度,找到所有d(i,j)中第k小的,输出其长度。
    思路:k最大为400,暴力floyd,对所有边根据权值排序,计算前min(k,m)条边可以组成的最短路长度,存入数组,第k小的就是答案,由于点的数值可能很大,所以Floyd之前先对点进行离散化处理。
     
     1 //
     2 // Created by mile on 2019/7/26.
     3 //
     4 // 离散化点+Floyd
     5  
     6 #include <bits/stdc++.h>
     7  
     8 #define ps push
     9 #define pb push_back
    10 #define mp make_pair
    11  
    12 using namespace std;
    13  
    14 vector<pair<long long, pair<int, int>>> edges;
    15 vector<int> ver;
    16 long long dis[1005][1005];
    17  
    18 int main()
    19 {
    20     int n, m, k;
    21     scanf("%d%d%d", &n, &m, &k);
    22     for(int i = 1; i <= m; ++i) {
    23         int u, v, w;
    24         scanf("%d%d%d", &u, &v, &w);
    25         edges.pb(mp(w, mp(u, v)));
    26     }
    27     sort(edges.begin(), edges.end());
    28     for(int i = 0; i < min(m, k); ++i) {
    29         ver.pb(edges[i].second.first);
    30         ver.pb(edges[i].second.second);
    31     }
    32     sort(ver.begin(), ver.end());
    33     ver.erase(unique(ver.begin(), ver.end()), ver.end());
    34     int sz = ver.size();
    35     memset(dis, 0x3f, sizeof(dis));
    36     for(int i = 0; i <= sz; i++) {
    37         dis[i][i] = 0;
    38     }
    39  
    40     for(int i = 0; i < min(m, k); i++) {
    41         int x = lower_bound(ver.begin(), ver.end(), edges[i].second.first)-ver.begin();
    42         int y = lower_bound(ver.begin(), ver.end(), edges[i].second.second)-ver.begin();
    43         dis[x][y] = dis[y][x] = min(dis[x][y], edges[i].first);
    44     }
    45     vector<long long> ans;
    46     for(int i = 0; i < sz; i++) {
    47         for(int j = 0; j < sz; j++) {
    48             for(int k = 0; k < sz; k++) {
    49                 dis[j][k] = min(dis[j][k], dis[j][i]+dis[i][k]);
    50             }
    51         }
    52     }
    53     for(int i = 0; i < sz; i++) {
    54         for(int j = i+1; j < sz; j++) {
    55             ans.pb(dis[i][j]);
    56         }
    57     }
    58     sort(ans.begin(), ans.end());
    59     printf("%lld
    ", ans[k-1]);
    60     return 0;
    61 }
    View Code
  • 相关阅读:
    Leetcode 33.搜索旋转排序数组
    Leetcode 32.最长有效括号
    Leetcode 31.下一个排列
    Leetcode 30.与所有单词相关联的子串
    Leetcode 25.k个一组翻转链表
    Leetcode 24.两两交换链表中的节点
    做数据分析需要“搞”人?
    求职互联网数据分析,如何准备行业知识?
    如何利用Social Listening从社会化媒体中“提炼”有价值的信息?
    运营实操|如何利用微信后台数据优化微信运营
  • 原文地址:https://www.cnblogs.com/mile-star/p/11252621.html
Copyright © 2011-2022 走看看