Educational Codeforces Round 75 (Rated for Div. 2)

Preface

我要开始打Codeforces了,这是我的第二场比赛,本来以为可以快速上分的,谁知在pupil的路上越走越远。打算补题补到D题,在三天内完成。

本场战绩:
Cost Time: 2 hours
Solve: 1
Rank: 3989
Rating: -45

Question

A. Broken Keyboard
题目大意:找出输入串中连续个数为奇数的字母,按字典序输出。
解法:简单模拟,对出现连续个数为奇数的字母做标记,然后遍历标记数组输出即可。

#include 

using namespace std;
const int maxn = 505;
int T, n;
string s;
int mark[maxn];

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> T;
    while (T--) {
        cin >> s;
        int idx = 0, cnt = 1;
        char t = s[0];
        memset(mark, 0, sizeof(mark));
        for (int i = 1; i < s.length(); i++) {
            if (t == s[i]) {
                cnt++;
            } else {
                if (cnt & 1) mark[t - 'a'] = 1;
                t = s[i];
                cnt = 1;
            }
        }
        if (cnt & 1) mark[t - 'a'] = 1;
        for (int i = 0; i < 26; i++) {
            if (mark[i]) {
                putchar(i + 'a');
            }
        }
        putchar('\n');
    }
    return 0;
}

B. Binary Palindromes
题目大意:给定n个只包含0和1的字符串,串与串之间任意位置的字符可以相互交换,求最终可以组成多少个回文串。

解法
由手动模拟可以知道,所有的0和1可以随意放置,于是有了下面两种解法

  1. 既然最后组成的是回文串,我们就只用计算最后能组成多少个完整回文串的一半,当然0和1的数量也要相应减半,例如我们想构成1001,我们只要组成10即可。我们可以先计算0和1的数量,然后然后将0和1的数量各减半,随意填入长度为 l e n ( s i ) / 2 len(s_i)/2 len(si)/2的串中,得到的串的个数就是答案。
  2. 通过观察多组样例,我们可以发现,组成回文串的数量要么是 n n n,要么是 n − 1 n-1 n1,而出现 n − 1 n-1 n1的情况恰是当所给串的长度都是偶数,且0和1的数量都是奇数。
#include 

using namespace std;
const int maxn = 505;
int T, n;
string s;

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> T;
    while (T--) {
        cin >> n;
        int len = 0, ones = 0, flag = 0;
        for (int i = 0; i < n; i++) {
            cin >> s;
            if (s.length() & 1) flag = 1;
            for (int j = 0; j < s.length(); j++)
                ones += s[j] - '0';
        }
        if (!flag && (ones & 1)) cout << n - 1 << endl;
        else cout << n << endl;
    }
    return 0;
}

C. Minimize The Integer
题目大意:给一个数字串,我们可以交换任意次它相邻且对应位不同为奇数或偶数的数,例如给定串"4532",4和5之间可以交换,4和3之间不能交换(不相邻),5和3不能交换(因为都是素数)。最后要使得得到的数最小。
解法:按顺序将奇数和偶数都提取出来,然后将奇数和偶数小的一方先填入,以此类推(有点像归并排序)

PS:这个方法是借鉴scnucjh大佬的。

#include 

using namespace std;
const int maxn = 505;
int T;
string s;

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> T;
    while (T--) {
        cin >> s;
        vector<int> a, b, ans;
        for (int i = 0; i < s.length(); i++) {
            int t = s[i] - '0';
            if (t & 1) a.push_back(t);
            else b.push_back(t);
        }
        int i = 0, j = 0;
        while (i < a.size() && j < b.size()) {
        	//将小的数先填入串中
            if (a[i] < b[j]) ans.push_back(a[i++]);
            else ans.push_back(b[j++]);
        }
        //最后将剩余的部分也填入串中
        while (i < a.size()) ans.push_back(a[i++]);
        while (j < b.size()) ans.push_back(b[j++]);
        for (int i = 0; i < ans.size(); i++)
            putchar(ans[i] + '0');
        putchar('\n');
    }
    return 0;
}

D. Salary Changing
题目大意:给定n个员工和s块钱,每个员工要给的工资在 [ l i , r i ] [l_i,r_i] [li,ri]这个区间内,现在要使所给工资的中位数最大。
解法:最优化问题一般考虑二分法,为了保证找到的x可以成为中位数,我们先对 l i , r i l_i,r_i li,ri从大到小排序,然后二分查找中位数的值。判断条件主要考虑这个数能不能在中间位置,以及当它在中间位置是,是否够钱支付给各个员工。

#include 

using namespace std;
typedef long long ll;
const int maxn = 2e5 +10;
int T, n;
ll s;

struct People {
    int a, b;
    bool operator < (const People &p) {
        return a^p.a ? a > p.a : b > p.b
;    }
} p[maxn];

template <class T>
int read(T &res) {
    char c; int sgn;
    if (c = getchar(), c == EOF) return 0;
    while (c != '-' && (c < '0' || c > '9')) c = getchar();
    sgn = (c == '-') ? -1 : 1;
    res = (c == '-') ? 0 : (c - '0');
    while (c = getchar(), c >= '0' && c <= '9') res = res * 10 + (c - '0');
    res *= sgn;
    return 1;
}

template <class T>
void write(T x) {
    if (x > 9) write(x / 10);
    putchar(x % 10 + '0');
}

template <class T>
void writeln(T x) {
    write(x);
    putchar('\n');
}

int check(ll x) {
    ll cnt = 0, half = (n + 1) >> 1, sum = 0;
    for (int i = 1; i <= n; i++) {
        if (p[i].a >= x) {
            sum += p[i].a;
            cnt++;
        } else {
            if (p[i].b >= x && cnt < half) {
                sum += x;
                cnt++;
            } else {
                sum += p[i].a;
            }
        }
    }
    if (cnt < half) return 0;
    return sum <= s;
}

int main()
{
    read(T);
    while(T--) {
        read(n); read(s);
        for (int i = 1; i <= n; i++) {
            read(p[i].a);
            read(p[i].b);
        }
        sort(p + 1, p + n + 1);
        ll l = 1, r = 1e18, mid;
        while (l <= r) {
            mid = (l + r) >> 1;
            if (check(mid)) l = mid + 1;
            else r = mid - 1;
        }
        writeln(r);
    }
    return 0;
}

PS:参考了这篇博客:https://www.cnblogs.com/Kylin-xy/p/11735955.html

Rating View

Educational Codeforces Round 75 (Rated for Div. 2)_第1张图片

你可能感兴趣的:(Educational Codeforces Round 75 (Rated for Div. 2))