码迷,mamicode.com
首页 > 其他好文 > 详细

Educational Codeforces Round 75 (Rated for Div. 2)

时间:2019-11-09 10:03:29      阅读:77      评论:0      收藏:0      [点我收藏+]

标签:strlen   工资   位置   ==   its   oar   假设   pre   归并   

A - Broken Keyboard

题意:键盘一些键坏了,按一下出俩字,给一个串,判断哪些键没坏。

题解:那肯定是至少有一段连续相同字母区间内的个数为奇数的没坏。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

char s[505];

int main() {
#ifdef KisekiPurin
    freopen("KisekiPurin.in", "r", stdin);
#endif // KisekiPurin
    int t;
    scanf("%d", &t);
    while(t--) {
        scanf("%s", s + 1);
        int n = strlen(s + 1);
        vector<char> ans;
        for(int i = 1; i <= n; ++i) {
            int j = i;
            while(j + 1 <= n && s[j + 1] == s[i])
                ++j;
            if((j - i + 1) & 1)
                ans.push_back(s[i]);
            i = j;
        }
        sort(ans.begin(), ans.end());
        ans.resize(unique(ans.begin(), ans.end()) - ans.begin());
        for(auto c : ans)
            printf("%c", c);
        printf("\n");
    }
}

B - Binary Palindromes

题意:给n个01串,可以在串之间任意交换字符,操作次数不限。求能构造的最多有几个回文串。

题解:一个直观的猜测是答案是n或者n-1(把一个串作为垃圾桶存放多出来的(奇数个的)那个位)。假如是全0或者全1就肯定都是回文串,否则,假如是其中的偶数个发生的翻转,全部丢在一个串的两侧翻转即可。假如是奇数个发生翻转,可以把奇数的那次放在某个奇数长度串的中间。

具体来说,设有a个0,b个1,假设a,b都是偶数,那么全部乱丢一通就可以了。假设a,b一奇一偶,那么把奇的那次丢给一定会出现至少一个的奇数串就可以了。假如a,b两个奇数,那么就判断有多少个奇数串,有两个以上奇数串就n,否则n-1(没有奇数串,必须破坏一个偶数串)。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

char s[55];

int main() {
#ifdef KisekiPurin
    freopen("KisekiPurin.in", "r", stdin);
#endif // KisekiPurin
    int t;
    scanf("%d", &t);
    while(t--) {
        int n;
        scanf("%d", &n);
        int a = 0, b = 0, c = 0;
        for(int j = 1; j <= n; ++j) {
            scanf("%s", s + 1);
            int l = strlen(s + 1);
            c += l & 1;
            for(int i = 1; i <= l; ++i) {
                if(s[i] == '0')
                    ++a;
                else
                    ++b;
            }
        }
        printf("%d\n", n - ((a & 1) && (b & 1) && (c == 0)));
    }
}

C - Minimize The Integer

题意:给一个数字串,假如两个相邻位置的奇偶不同就可以交换位置,求最小的串,可以有前导零。

题解:看起来就是奇数的顺序保持不变,偶数的顺序保持不变,这两个东西可以互相渗透。看起来像归并排序。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

char s[300005];
queue<char> odd, even;

int main() {
#ifdef KisekiPurin
    freopen("KisekiPurin.in", "r", stdin);
#endif // KisekiPurin
    int t;
    scanf("%d", &t);
    while(t--) {
        scanf("%s", s + 1);
        int n = strlen(s + 1);
        for(int i = 1; i <= n; ++i) {
            if((s[i] - '0') & 1)
                odd.push(s[i]);
            else
                even.push(s[i]);
        }
        string ans;
        while(odd.size() && even.size()) {
            if(odd.front() < even.front()) {
                ans += odd.front();
                odd.pop();
            } else {
                ans += even.front();
                even.pop();
            }
        }
        while(odd.size()) {
            ans += odd.front();
            odd.pop();
        }
        while(even.size()) {
            ans += even.front();
            even.pop();
        }
        cout << ans << endl;
    }
}

D - Salary Changing

题意:给s块钱,n(n是奇数)个人,每个人有个工资区间[l,r],发不超过s的工资使得中位数最大。

题解:一个简单的思路就是二分中位数m,然后验证填充这个中位数要不要s块钱,l>=m的肯定发l,假设发了a个,那么看看剩下的人有没有办法使得中位数为m,假如可以,则包含中位数m的区间就发m直到使得m为中位数,剩下的发l(所以这一步要按l从大到小贪心)。做法是扫一遍取出包含中位数m的人(按l排序,但可以先验证可行再排),右侧于中位数的人全部发l并统计数量,左侧于中位数的人全部发l,包含中位数的全部发m到中位数恰为m剩下的发l,复杂度两个log。睡醒后发现其实要找的是前k个,直接用nth_element()更快,复杂度一个log。

Educational Codeforces Round 75 (Rated for Div. 2)

标签:strlen   工资   位置   ==   its   oar   假设   pre   归并   

原文地址:https://www.cnblogs.com/KisekiPurin2019/p/11823903.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!