Educational Codeforces Round 101 (Rated for Div. 2)

Educational Codeforces Round 101 (Rated for Div. 2)

A. Regular Bracket Sequence

题意: 就是给你一个由 ‘(’ ,’)’ 或 ‘?’ 组成的字符串 ,’?'替换为 '(’ 或 ‘)’ ,不能改变位置。

**题解: ** 看第一个和最后一个字符是否符合,并且长度是否是2的倍数就好了。原先用栈写的代码,去模拟整个过程,wa了一发,赛后分析是因为处理不了(?)?的输入清空,而且没有使用到只有2的(的情况。

**代码: **

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;
typedef pair<int, int> PII;
int const MAXN = 2e5 + 10;
int n, m, T;

int main() {
    cin >> T;
    while(T--) {
        string s;
        cin >> s;
        if ((s.size() & 1) || s[0] == ')' || s.back() == '(') {
            puts("NO");
            continue;
        }
        puts("YES");
    }   
    return 0;
}

B. Red and Blue

题意: 有一个数组,由标记为R或B的数字组成,现在这个数组丢了。但是给你了两组数组R跟B,顺序为他们在原数组的出现顺序,现在让你把他们排回去,找出一种排序方式使得f(a)=max(0,a1,(a1+a2),(a1+a2+a3),…,(a1+a2+a3+⋯+an+m))最大。

**题解: ** 要和原数组的出现顺序一致,那么就是把2个数组按照原来的位置拼接在一起。那现在使得拼接出来的数组的某个前缀最大,所有的情况一共有n * m种,其中最大的情况就是2个最大的前缀相加。

**代码: **

#include <bits/stdc++.h>

using namespace std;

int n, m, T;
const int INF = 1e9;

int main() {
    cin >> T;
    while (T--) {
        cin >> n;
        int num;
        int sum1 = 0;
        int res1 = -INF;

        for (int i = 0; i < n; i++) {
            cin >> num;
            sum1 += num;
            res1 = max(res1, sum1);
        }
        if (res1 < 0) res1 = 0;
        cin >> m;
        int sum2 = 0;
        int res2 = -INF;
        if (m == 0) res2 = 0;
        for (int i = 0; i < m; i++) {
            cin >> num;
            sum2 += num;
            res2 = max(res2, sum2);
        }
        if (res2 < 0) res2 = 0;
        printf("%d\n", res1 + res2);
    }
    return 0;
}

C. Building a Fence

题意: 给你一堆高度去建围栏,这些围栏必须有公共边,第一个和最后一个围栏必须挨着地面,其他围栏可以浮空,但不能超过k - 1

**题解: ** 维护low和high作为围栏的最小、最大值,每次都更新下围栏的上下界。

**代码: **

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;
typedef pair<int, int> PII;
int const MAXN = 2e5 + 10;
int n, m, T, h[MAXN], k;

int main() {
    cin >> T;
    while(T--) {
        scanf("%d%d", &n, &k);
        for (int i = 1; i <= n; ++i) scanf("%d", h + i);
        int flg = 1, low = h[1], high = h[1] + k;
        for (int i = 2; i <= n - 1; ++i) {
            if (high <= h[i] || low >= h[i] + 2 * k - 1) {
                flg = 0;
                break;
            }
            low = max(h[i], low - k + 1);
            high = min(h[i] + 2 * k - 1, high + k - 1);
        }
        if (high <= h[n] || low >= h[n] + k) flg = 0;
        if (flg) puts("YES");
        else puts("NO");
    }
    return 0;
}

D. Ceil Divisions

题意: 给定一个有n个数的a数组,每次操作选择两个数x,y(x≠y),使得ax=⌈ax/ay⌉。

要求执行不多于n+5个操作,将a数组变成有n-1个1和1个2的数组。输出依次进行的操作,不要求最小化。

**题解: ** 可以构造出 2 1 2^1 21, 2 4 2^4 24, 2 8 2^8 28, n,这4个数字,对于这4个数字之间的数字全部除于n,那么就会全部变成1;对于这4个数字之间,大的除以小的,最多只会要2次就能变成1。最后这个操作到达2结束。

**代码: **

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;
typedef pair<int, int> PII;
int const N = 3e5 + 10;
int n, m, T;
int num[100];

int main() {
    cin >> T;
    num[1] = 2;
    for (int i = 2; i <= 5; i++) num[i] = num[i - 1] * num[i - 1];
    while (T--) {
        int res = 0;
        scanf("%d", &n);
        int pos = 2;
        for (int i = 2; i < n; i++) {
            int flg = 0;
            for (int j = 1; j <= 5; j++) 
                if (i == num[j]) {
                    flg = 1;
                    pos = j;
                }

            if (flg) continue;
            res++;
        }
        res += 2;
        for (int i = pos; i >= 2; i--) res += 2;
        printf("%d\n", res);
        for (int i = 2; i < n; i++) {
            int flg = 0;
            for (int j = 1; j <= 5; j++) {
                if (i == num[j]) {
                    flg = 1;
                    pos = j;
                }
            }
            if (flg) continue;
            printf("%d %d\n", i, n);
        }
        printf("%d %d\n", n, num[pos]);
        printf("%d %d\n", n, num[pos]);
        for (int i = pos; i >= 2; i--) {
            printf("%d %d\n", num[i], num[i - 1]);
            printf("%d %d\n", num[i], num[i - 1]);
        }
    }
    return 0;
}

E.A Bit Similar

题意: 给你一个长度为n的字符串s,要求找到一个长度为k的字符串,该字符串和s的所有长度为k的子串都至少有一个相同的字符

**题解: ** 我们可以把s的所有子串的反码都放进一个set内,则set内为与所有子串都不相同的集合,存储的时候只需要存储后30位。然后枚举所有情况,如果在集合没有找到,那么说明这个字符串可以。

**代码: **

#include <bits/stdc++.h>
using namespace std;
int n, k; 
string s;
int main() {
    int q; cin >> q;
    while(q--) {
        cin >> n >> k;
        cin >> s;
        int bit = min(k, 30);
        set<int> st;
        int pre = 0;
        for(int i = k - 1; i < s.size(); i++) {
            if(pre < i - k + 1) pre++;
            while(s[pre] == '1' && pre < i) pre++;
            if(pre < i - bit + 1) continue;
            int val = 0;
            for(int j = i - bit + 1; j <= i; j++) val = (val << 1) | (s[j] == '0');
            st.insert(val);
        }
        bool flg = false;
        for(int ans = 0; ans < 1 << bit; ans++) 
            if(st.find(ans) == st.end()) { 
                cout << "YES" << endl;  
                for(int j = 0; j < k - bit; j++) cout << "0";
                for(int j = bit - 1; j >= 0; j--) cout << (ans >> j & 1);
                cout << endl;
                flg = true;
                break;
            }
        if(!flg) cout << "NO" << endl;
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值