Codeforces Round #787 (Div. 3)和Codeforces Round #790 (Div. 4) ABC/ABCDE

 

目录

 Codeforces Round #787 (Div. 3)

A

B 模拟/贪心

 C 思维

Codeforces Round #790 (Div. 4) 

A

B

C纯暴力

D 数学/思维

E 二分贪心/前缀和


 Codeforces Round #787 (Div. 3)

A

 讨论极端情况即可

//#include<bits/std c++.h>
#include <iostream>
#include<ctime>
#include<math.h>
#include<string>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<cstring>
#include<algorithm>
#include<limits.h>
#include<unordered_map>
#include<unordered_set>
#define ll long long
#define int ll
#pragma warning (disable:4996);
using namespace std;
const int N = 1e4+10;
int T;
int a, b, c, x, y;
signed main()
{
    ios::sync_with_stdio(false); cout.tie(NULL);
#ifndef ONLINE_JUDGE
    //freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
#endif // !ONLINE_JUDGE
    cin >> T;
    while (T--) {
        cin >> a >> b >> c >> x >> y;
        if (a + c < x || b + c < y) {
            cout << "NO" << endl;

        }
        else if(a>=x||b>=y) {
            cout << "YES" << endl;
        }
        else {
            if ((x - a) + (y - b) > c) {
                cout << "NO" << endl;
            }
            else {
                cout << "YES" << endl;
            }
        }

    }
    return 0;
}

B 模拟/贪心

 题目是说给定一个序列,每次你能对其中一个让其中一个元素变为原来的一半(向下取整 ),问能否使这个序列严格递增。如果能则输出最小步骤数。

思路就是从序列后面开始模拟减半操作这样才会保证步骤最小,如果在模拟过程中出现了非第一项,但值为0的情况则输出-1

这题数据很阴要注意0 n这个序列

//#include<bits/std c++.h>
#include <iostream>
#include<ctime>
#include<math.h>
#include<string>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<cstring>
#include<algorithm>
#include<limits.h>
#include<unordered_map>
#include<unordered_set>
#define ll long long
#define int ll
#pragma warning (disable:4996);
using namespace std;
const int N = 1e6+10;
int T,n;
int arr[N];

signed main()
{
    ios::sync_with_stdio(false); cout.tie(NULL);
#ifndef ONLINE_JUDGE
    //freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
#endif // !ONLINE_JUDGE
    cin >> T;
    while (T--) {
        cin >> n;
        int sum = 0;
        int ok = 0;
        int mn = INT_MAX;
        for (int j = 1; j <= n; j++) {
            cin >> arr[j];
            mn = min(arr[j], mn);
        }
            for (int j = n-1; j >= 1; j--) {
               
                if (arr[j] >= arr[j+1]) {
                    int cnt = 0;
                    
                    while (arr[j] >= arr[j+1]&&arr[j]!=0) {
                        arr[j] = arr[j] / 2;
                        cnt++;
                    }
                    if (j != 1 && arr[j] == 0) {
                        cout << -1 << endl;
                        ok = 1;
                        break;
                   }
                    if (j == 1 && arr[j + 1] == 0 && arr[j] == 0) {
                        cout << -1 << endl;
                        ok = 1;
                        break;
                    }
                    sum += cnt;
                }
               
            }
            if(!ok)
            cout << sum << endl;
    }


    return 0;
}

 C 思维

 题意:一队人来看画最后发现画没了,于是挨个询问,每个人有自己的回答,1表示自己看的时候画还在,0表示看的时候画没了,?表示不记得。问偷画的嫌疑人数

思路,想明白就很简单了,特判一下,最后一个人说1的话肯定是小偷,不用怀疑了。然后其他情况下的人数就是最后一个1到第一个0之间的人数

//#include<bits/std c++.h>
#include <iostream>
#include<ctime>
#include<math.h>
#include<string>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<cstring>
#include<algorithm>
#include<limits.h>
#include<unordered_map>
#include<unordered_set>
#define ll long long
#define int ll
#pragma warning (disable:4996);
using namespace std;
const int N = 1e6+10;
int T,n;
int arr[N];

signed main()
{
    ios::sync_with_stdio(false); cout.tie(NULL);
#ifndef ONLINE_JUDGE
    //freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
#endif // !ONLINE_JUDGE
    cin >> T;
    while (T--) {
        string s;
        cin >> s;
        int n = s.length();
        if (n == 1) {
            cout << 1 << endl;
            continue;
        }
        if (s[n - 1] == '1')
        {
            cout << 1 << endl;//最后一个人这么说那肯定是假的
            continue;
        }
      
        int pos = 0;
        int ok = 0;
        int p1 = n-1;
        for (int j = 0; j < s.length(); j++) {
            if (s[j] == '1') {
                pos = j;
            }
            if (s[j] == '0'&&ok==0) {
                ok = 1;
                p1 = j;
            }
        }
        if (pos == p1)
            cout << p1+1 << endl;
        else if (pos > p1) {
            cout << pos-p1+1 << endl;
        }
        else
            cout <<p1-pos+1 << endl;
       
    }

    return 0;
}

Codeforces Round #790 (Div. 4) 

A

一张票可以视为六个数字组成的字符串,可能有前导零。

如果一张票的前三位数字之和与后三位数字之和相等,那么它是幸运的。

给你 T 张票,对于每张票,询问它是否幸运。(幸运输出 "YES",否则输出 "NO")

输入输出样例

输入 #1复制

5
213132
973894
045207
000000
055776

输出 #1复制

YES
NO
YES
YES
NO

pass

//#include<bits/std c++.h>
#include <iostream>
#include<ctime>
#include<math.h>
#include<string>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<cstring>
#include<algorithm>
#include<limits.h>
#include<unordered_map>
#include<unordered_set>
#include<regex>
using namespace std;

#define f first
#define s second
#define ll long long
#define int ll
#pragma warning (disable:4996);
const int N = 4e5 + 10;
int T, n, m, q;


signed main()
{
    ios::sync_with_stdio(false); cout.tie(NULL);
#ifndef ONLINE_JUDGE
    //freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
#endif // !ONLINE_JUDGE
    cin >> T;
    while (T--) {
        string s;
        cin >> s;
        int s1 = 0, s2 = 0;
        for (int j = 0; j < 3; j++) {
            s1 += (s[j] - '0');
           
        }
        for (int j = 3; j < 6; j++) {
            s2 += (s[j] - '0');

        }
            if(s1 == s2) {
            cout << "YES" << endl;
        }
        else {
            cout << "NO" << endl;
        
        }
    }



}

B

有 n 盒糖,第 i 盒糖中有 ai​ 颗糖。你有 n 个朋友,你想给每个朋友发一盒糖。

但是每盒糖的数量可能不一样,所以你想要吃掉一些糖,使得每盒糖中糖数相等。

注意:你可以在不同的盒子中吃掉不同数量的糖(可以不吃),但不能向任何盒子中加糖。

问你最少吃掉多少颗糖,才能完成目标。

输入输出样例

输入 #1

5
5
1 2 3 4 5
6
1000 1000 5 1000 1000 1000
10
1 2 3 5 1 2 7 9 13 5
3
8 8 8
1
10000000

输出 #1

10
4975
38
0
0

每个数量减去最小值

//#include<bits/std c++.h>
#include <iostream>
#include<ctime>
#include<math.h>
#include<string>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<cstring>
#include<algorithm>
#include<limits.h>
#include<unordered_map>
#include<unordered_set>
#include<regex>
using namespace std;

#define f first
#define s second
#define ll long long
#define int ll
#pragma warning (disable:4996);
const int N = 4e5 + 10;
int T, n, m, q;

int arr[N];
signed main()
{
    ios::sync_with_stdio(false); cout.tie(NULL);
#ifndef ONLINE_JUDGE
    //freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
#endif // !ONLINE_JUDGE
    cin >> T;
    while (T--) {
        cin >> n;
        int mn = 99999999;
        for (int j = 1; j <=n; j++) {
            cin >> arr[j];
            mn = min(mn, arr[j]);
        }
        int sum = 0;
        for (int j = 1; j <= n; j++) {
            sum += (arr[j] - mn);
        }
        cout << sum << endl;
    }



}

C纯暴力

 题意:给出n个m长的字符串,一对字符串中每个对应的字母相差的序号为距离。每个字母转换为对应字母要相差序号的步骤数。问n个字符串中转换为两个一样的字符串对的最少步骤。

没什么别的思路,数据也很水,三重循环秒了

//#include<bits/std c++.h>
#include <iostream>
#include<ctime>
#include<math.h>
#include<string>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<cstring>
#include<algorithm>
#include<limits.h>
#include<unordered_map>
#include<unordered_set>
#include<regex>
using namespace std;

#define f first
#define s second
#define ll long long
#define int ll
#pragma warning (disable:4996);
const int N = 4e5 + 10;
int T, n, m, q;

int arr[N];
signed main()
{
    ios::sync_with_stdio(false); cout.tie(NULL);
#ifndef ONLINE_JUDGE
    //freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
#endif // !ONLINE_JUDGE
    cin >> T;
    while (T--) {
        cin >> n>>m;
        string s[100];
        map<string, int>m1;
        for (int j = 1; j <= n; j++) {
            cin >> s[j];
            m1[s[j]] = 1;
        }
        int mn = 999999999;
        for (int j = 1; j <= n; j++) {
            for (int i = j+1; i <= n; i++) {
                int sum = 0;
                  for (int k = 0; k < m; k++) {
                      sum += abs(s[j][k] - s[i][k]);
                  }
                  mn = min(sum, mn);
            }
        }
        cout << mn << endl;
    }



}

D 数学/思维

 计算每条正对角线和逆对角线的值。然后枚举落脚点,求该点处正逆对角线和,然后取最大值即可。麻烦的点是对这个正逆对角线做hash取坐标,这样才能根据一个点得到该点的正逆对角线。可以发现,每一个点的x+y和x-y都只对应一条正或逆的对角线

//#include<bits/std c++.h>
#include <iostream>
#include<ctime>
#include<math.h>
#include<string>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<cstring>
#include<algorithm>
#include<limits.h>
#include<unordered_map>
#include<unordered_set>
#include<regex>
using namespace std;

#define f first
#define s second
#define ll long long
#define int ll
#pragma warning (disable:4996);
const int N = 200 + 10;
int T, n, m, q;



signed main()
{
    ios::sync_with_stdio(false); cout.tie(NULL);
#ifndef ONLINE_JUDGE
    //freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
#endif // !ONLINE_JUDGE
    cin >> T;
    while (T--) {
        cin >> n >> m;
        int arr[N][N];
        int len = n + m - 2;
        int d1[N]={0};
       unordered_map<int, int>d2;
        for (int y = 0; y < n; y++) {
            for (int x = 0; x < m; x++) {
                cin >> arr[y][x];
                d1[y + x] += arr[y][x];
                d2[y-x] += arr[y][x];//d2从m-1开始
            }
        }
        int t = m - 1;
        int mx = -99999999;
        for (int j = 0; j < n; j++) {
            for (int i = 0; i < m; i++) {
                mx = max(d1[j + i] + d2[j-i]-arr[j][i], mx);
            }
        }
        cout << mx << endl;

    }
}

E 二分贪心/前缀和

 题意:给出一个序列,和一个询问值,问最少从序列中拿出几个数使拿出的和大于等于询问值

首先可以想到,每次从大的取才可能保证最少的次数。所以先对序列进行排序。然后枚举要从大的开始拿几个才能大于等于询问值。但是这题数据非常大,直接枚举超时非常严重。所以可以想到二分来枚举从后往前要拿几个数。所以再用前缀和得到从大的开始拿几个的和是几,最后再用二分枚举即可。

//#include<bits/std c++.h>
#include <iostream>
#include<ctime>
#include<math.h>
#include<string>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<cstring>
#include<algorithm>
#include<limits.h>
#include<unordered_map>
#include<unordered_set>
#include<regex>
using namespace std;

#define f first
#define s second
#define ll long long
#define int ll
#pragma warning (disable:4996);
const int N = 2e5 + 10;
int T, n, m, q;
int arr[N], qq[N],d[N];
int bf(int k) {
    int l = 0, r = n + 1;
    int mid ;
    while (l + 1 != r) {
        mid = (l + r) >> 1;
        if (d[mid] >= k)
            r = mid;
        else
            l = mid;
    }
    return r;
}

signed main()
{
    ios::sync_with_stdio(false); cout.tie(NULL);
#ifndef ONLINE_JUDGE
    //freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
#endif // !ONLINE_JUDGE
    cin >> T;
    while (T--) {
        cin >> n>>q;
        int sum = 0;
        memset(d, 0, sizeof(d));
        memset(arr, 0, sizeof(arr));
        memset(qq, 0, sizeof(qq));
        for (int j = 1; j <= n; j++) {
            cin >> arr[j];
            sum += arr[j];
        }
   
        sort(arr + 1, arr + n + 1,greater<int>());
        for (int j = 1; j <=n; j++) {
            d[j] = d[j-1] + arr[j];
        }
        for (int j = 1; j <= q; j++) {
            cin >> qq[j];
            if (sum < qq[j])
            {
                cout << -1 << endl;
                continue;
            }
            int p = bf(qq[j]);
             cout <<  p << endl;
            
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值