Codeforces Round #799 (Div. 4) 赛后总结

A. Marathon

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4CpKBp1v-1655372744580)(https://cdn.acwing.com/media/article/image/2022/06/16/150003_94bac50bed-火狐截图_2022-06-16T07-32-54.845Z.png)]

思路:将 a n s ans ans 初始化为 3 3 3,剩下三个数跟第一个数比,若第一个数比剩下的数大则 ans -- ,最终剩下的数即为答案!

Code:

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

int main()
{
    int T;
    cin >> T;
    
    while (T -- )
    {
        int a, b, c, d;
        cin >> a >> b >> c >> d;
        
        int ans = 3;
        
        if (a > b) ans -- ;
        if (a > c) ans -- ;
        if (a > d) ans -- ;
        cout << ans << endl;
    }
    
    return 0;
}

B. All Distinct

在这里插入图片描述

思路:我们可以用 s e t set set 将数组内的元素去重,故设数组的大小为 n n n,所有出现过元素所构成的集合的大小是 s e t . s i z e ( ) set.size() set.size(),那么所有重复元素所构成集合的大小为 n − s e t . s i z e ( ) n-set.size() nset.size(),我们可以不断的在所有重复元素所构成集合中一直消去两个元素,直到该集合内的元素为 0 0 0。此时我们开始分类讨论:

  • n − s e t . s i z e ( ) n-set.size() % 2 = 0 nset.size() 时,此时可以说明所有重复元素所构成集合中的元素刚好可以被消耗殆尽,此时答案就是 s e t . s i z e ( ) set.size() set.size()
  • n − s e t . s i z e ( ) n-set.size() % 2 = 1 nset.size() 时,此时可以说明所有重复元素所构成集合中的元素被消耗殆尽时,还要添上1个才能使得被变化的集合中无重复元素,所以答案就是 s e t . s i z e ( ) − 1 set.size()-1 set.size()1

Code:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <set>

using namespace std;

int main()
{
    int T;
    cin >> T;
    
    while (T -- )
    {
        int n;
        cin >> n;
        
        set<int> s;
        
        for (int i = 0; i < n; i ++ )
        {
            int x;
            cin >> x;
            s.insert(x);
        }
        
        if ((n - s.size()) % 2 == 0)
            cout << s.size() << endl;
        else
            cout << s.size() - 1 << endl;
    }
    
    return 0;
}

C.Where’s the Bishop?

在这里插入图片描述

思路:反正图也不大,直接遍历一下全图,找一下该点的四个方位是否都是#,若是则该位置就是答案,返回这个位置的下表即可!

Code:

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 10;

char g[N][N];
int res[2];

int dx[4] = {1, 1, -1, -1}, dy[4] = {1, -1, 1, -1};

void bfs()
{
    for (int i = 0; i < 8; i ++ )
        for (int j = 0; j < 8; j ++ ) 
        {
            bool flag = false;
            for (int k = 0; k < 4; k ++ ) 
            {
                int x = i + dx[k], y = j + dy[k];
                if (x >= 0 && x < 8 && y >= 0 && y < 8)
                {
                    if (g[x][y] != '#')
                    {
                        flag = true;
                        break;
                    }
                }
                else
                {
                    flag = true;
                    break;
                }
            }
            if (!flag)
            {
                res[0] = i, res[1] = j;
                return;
            }
        }
}

int main()
{
    int T;
    cin >> T;
    
    while (T -- )
    {
        for (int i = 0; i < 8; i ++ )
            for (int j = 0; j < 8; j ++ )
                cin >> g[i][j];
                
        bfs();
        
        cout << res[0] + 1 << " " << res[1] + 1 << endl;
    }
    
    return 0;
}

D. The Clock

在这里插入图片描述

思路:把所有数全部化成分钟,然后预处理一下从0~1439中所有的回文时间,最后以 x x x 为偏移量,以所给的开始时间为初始时间,直到第二次循环到开始时间的时候停止,统计一下这段时间内的回文时间!

Code:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <set>

using namespace std;

set<int> s;

void init()
{
    for (int i = 0; i < 1440; i ++ )
    {
        int m = i % 60;
        int n = i / 60;
        
        string str1 = to_string(n);
        string str2 = to_string(m);
        if (n < 10)
            str1 = "0" + str1;
        if (m < 10)
            str2 = "0" + str2;
        
        if (str1[0] == str2[1] && str1[1] == str2[0])
            s.insert(i);
    }
}

int main()
{
    int n;
    cin >> n;
    init();
    
    while (n -- )
    {
        string str;
        int x;
        cin >> str >> x;
        
        int ans = 0;
        int m = ((str[0] - '0') * 10 + (str[1] - '0')) * 60 + (str[3] - '0') * 10 + (str[4] - '0');
        bool flag = false;
        for (int i = m; ; i += x)
        {
            i = i % 1440;
            if (flag && i == m)
                break;
            flag = true;
            if (s.count(i))
                ans ++ ;
        }
                
        cout << ans << endl;
    }
    
    return 0;
}

E.Binary Deque

在这里插入图片描述

思路:对于该题目来说我们只需要采用双指针,找出最长包含 s s s 个1的子序列,最终答案就是总长度-最长包含 s s s 个1的子序列的长度。

Code:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>

using namespace std;

const int N = 2e5 + 10;

int main()
{
    int T;
    cin >> T;
    
    while (T -- )
    {
        int n, x;
        int a[N];
        cin >> n >> x;
        
        int sum = 0;
        int s = 0;
        for (int i = 0; i < n; i ++ ) 
        {
            cin >> a[i];
            s += a[i];
        }
        
        if (s < x)
            cout << -1 << endl;
        else
        {
            int l = 0, ans = 0;
            for (int i = 0, j = 0; j < n; j ++ ) 
            {
                sum += a[j];
                if (sum == x)
                    l = j - i + 1;
                if (sum > x)
                {
                    while (a[i] != 1) i ++ ;
                    sum -- ;
                    i ++ ;
                }
                ans = max(ans, l);
            }
            cout << n - ans << endl;
        }
    }
    
    return 0;
}

F.3SUM

在这里插入图片描述

思路:

  • 先进行初始化操作,将所有可能构成尾数为 3 3 3 的3个数变为字符串送入set中。

  • 然后将所有数的最后一位截取出来送入 a a a 数组里面(这样可保证所有数字都在0~9这个区间上),且保证 a a a 数组里面相同的数字不超过 3 3 3 个(因为在0~9这个区间内,最多可以凑出3,13,23这三个数字,凑出3只需要最多3个1,凑出13也最多只需要2个相同的数,凑出23也最多只需要2个相同的数,至此我们就把整个数组的范围压缩到27以内!)

  • 最后三层遍历看一下这三组所构成的字符串在不在set中,如果在则直接输出YES,若遍历完整个数组都没有的话,则输出NO

Code:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <set>
#include <map>

using namespace std;

set<string> s;

void init()
{
    for (int i = 0; i < 10; i ++ )
        for (int j = i; j < 10; j ++ )
            for (int k = j; k < 10; k ++ ) 
                if (i + j + k == 3 || i + j + k == 13 || i + j + k == 23)
                    s.insert(to_string(i) + to_string(j) + to_string(k));
}

int main()
{
    int T;
    cin >> T;
    init();
    
    while (T -- )
    {
        int n;
        string str;
        vector<int> a;
        cin >> n;
        map<int, int> m;
        
        while (n -- )
        {
            cin >> str;
            int x = str[str.size() - 1] - '0';
            if (m[x] < 3)
            {
                a.push_back(x);
                m[x] ++ ;
            }
        }
        
        sort(a.begin(), a.end());
        
        bool flag = false;
        int size = a.size();
        
        for (int i = 0; i < size; i ++ )
            for (int j = i + 1; j < size; j ++ )
                for (int k = j + 1; k < size; k ++ )
                {
                    string ss = to_string(a[i]) + to_string(a[j]) + to_string(a[k]);
                    if (s.count(ss))
                    {
                        flag = true;
                        break;
                    }
                }
        if (!flag)
            puts("NO");
        else
            puts("YES");
    }
    
    return 0;
}

G.2^Sort

在这里插入图片描述

思路:

  • 我们只需要额外开辟一个 b b b 数组,来记录是否a[i] < a[i + 1] * 2
  • 然后从0到 k k k 将所有的 b b b 数组元素加起来,记做 s u m sum sum
  • sum == k,则答案 ans ++
  • 然后再次从 k k k 开始到 n − 1 n - 1 n1,每一次 s u m sum sum 加上当前的 b b b,然后再减去 k k k 之前的 b b b ,若sum == k 的话,则答案 ans ++

Code:

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 2e5 + 10;

int main()
{
    int T;
    cin >> T;
    
    while (T -- ) 
    {
        int n, k;
        cin >> n >> k;
        int a[N], b[N];
        for (int i = 0; i < n; i ++ ) cin >> a[i];
        
        for (int i = 0; i < n; i ++ ) b[i] = (a[i] < a[i + 1] * 2);
        
        int sum = 0;
        int res = 0;
        
        for (int i = 0; i < k; i ++ ) sum += b[i];
        
        if (sum == k) res ++ ;
        
        for (int i = k; i < n - 1; i ++ ) 
        {
            sum += b[i];
            sum -= b[i - k];
            if (sum == k) res ++ ;
        }
        
        cout << res << endl;
    }
    return 0;
}

H.Gambling

在这里插入图片描述

思路:即找出一个区间使得众数的个数要比非众数的个数要大

  • 先将所有相同的数字的下标存入一个数组中去。
  • 然后遍历一下每个元素所存入的数组 a a a,算出在数组 a a a 中,值为 x x x 的元素减去值不为 x x x 元素的差,即 i − j + 1 − ( a i − a j − ( i − j + 1 ) ) i-j+1-(a_i-a_j-(i - j + 1)) ij+1(aiaj(ij+1)),我们整理一下 2 i − a i − 1 + a j − 2 j 2i-a_i-1+a_j-2j 2iai1+aj2j,不变的是 2 i − a i − 1 2i-a_i-1 2iai1,变化的是 a j − 2 j a_j-2j aj2j我们记为 t t t 最后使得 t t t 最大,顺便记录一下左端点 a i a_i ai

Code:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>

using namespace std;

int main()
{
    int T;
    cin >> T;
    
    while (T -- ) 
    {
        int n;
        cin >> n;
        map<int, vector<int>> m;
        
        for (int i = 1; i <= n; i ++ )
        {
            int x;
            cin >> x;
            m[x].push_back(i);
        }
        
        int mx = 0, ans, l, r;
        for (auto &[x, a] : m)
        {
            int t = -1e9, pos;
            for (int i = 0; i < a.size(); i ++ ) 
            {
                if (a[i] - 2 * i > t)
                    t = a[i] - 2 * i, pos = a[i];
                int now = 2 * i - a[i] + t + 1;
                if (now > mx)
                    mx = now, ans = x, l = pos, r = a[i];
            }
        }
        
        cout << ans << " " << l << " " << r << endl;
    }
    
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Nie同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值