Educational Codeforces Round 149 (Rated for Div. 2)

发布时间 2023-05-30 21:50:53作者: PHarr

A. Grasshopper on a Line

#include <bits/stdc++.h>

using namespace std;

#define int long long

void solve(){
    int x , k;
    cin >> x >> k;
    if( x % k == 0 ){
        cout << "2\n" << x - 1 << " " << 1 << "\n";
    }else{
        cout << "1\n" << x << "\n";
    }
}

int32_t main() {
    ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
    int t;
    cin >> t;
    while( t -- )
        solve();

        return 0;

}

B. Comparison String

直接找到连续相同且最长的段即可。

#include <bits/stdc++.h>

using namespace std;

#define int long long

void solve(){
    int n;
    string s;
    cin >> n >> s;
    int res = 0 , last = '.', cnt = 0;
    for( auto i : s ){
        if( last == i ) cnt ++;
        else{
            last = i , cnt = 1;
        }
        res = max( res , cnt );
    }
    cout << res + 1<< "\n";
    return ;
}

int32_t main() {
    ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
    int t;
    cin >> t;
    while( t -- )
        solve();

    return 0;

}

C. Best Binary String

连续的问号和两端的任意一个相同即可。

#include <bits/stdc++.h>

using namespace std;

#define int long long

void solve() {
    int n;
    string s;
    cin >> s;
    n = s.size();
    if( s[0] == '?' ) s[0] = '0';
    if( s[n-1] == '?' ) s[n-1] = '1';
    for( int i = 1 ; i < n-1 ; i ++ ){
        if( s[i] == '?' ){
            int j = i;
            while( s[j] == '?' ) j ++;
            if( s[i-1] == '1' && s[j] == '1' )
                for( int l = i ; l < j ; l ++ ) s[l] = '1';
            else
                for( int l = i ; l < j ; l ++ ) s[l] = '0';
            i = j;
        }
    }
    cout << s << "\n";


    return;
}

int32_t main() {
    ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
    int t;
    cin >> t;
    while (t--)
        solve();

    return 0;

}

D. Bracket Coloring

跑两种括号匹配,然后正序的括号匹配染成一种颜色,反序的括号匹配染成另一种颜色即可。

#include <bits/stdc++.h>

using namespace std;

#define int long long

void solve() {
    int n;
    string s;
    cin >> n >> s;
    if (n & 1) {
        cout << "-1\n";
        return;
    } else {
        int a = 0, b = 0;
        for (auto i: s)
            if (i == '(') a++;
            else b++;
        if (a != b) {
            cout << "-1\n";
            return;
        }
    }
    n = s.size();
    int cnt = 0, st = -1, p = 0;
    vector<pair<int, int>> res;
    for (auto i: s) {
        if (i == '(') {
            if (st == -1) st = 1, cnt = 1, p = 1;
            else if (st == 1) cnt++, p++;
            else if (cnt == 0) {
                res.emplace_back(st, p);
                st = 1, cnt = 1, p = 1;
            } else cnt--, p++;
        } else {
            if (st == -1) st = 2, cnt = 1, p = 1;
            else if (st == 2) cnt++, p++;
            else if (cnt == 0) {
                res.emplace_back(st, p);
                st = 2, cnt = 1, p = 1;
            } else cnt--, p++;
        }
    }
    res.emplace_back( st , p );
    if( res.size() == 1 ){
        cout << "1\n";
        for( int i = 1 ; i <= n ; i ++ )
            cout << "1 ";
        cout << "\n";
        return;
    }
    cout << "2\n";
    for (auto [a, b]: res) {
        while (b) cout << a << " ", b--;
    }
    cout << "\n";

    return;
}

int32_t main() {
    ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
    int t;
    cin >> t;
    while (t--)
        solve();

    return 0;
}

E. Playoff Fixing

首先对于某回合中那些人输其实是固定的,比如\(k=3\)时,赢的人一定是\(1,2,3,4\)输的人一定是\(5,6,7,8\)

这样的话,要保证每一对中必须是一个前一半的和一个后一半的。这样的话只需要统计出后一半需要放的人是数量\(cnt\)这样就有\(cnt!\)种情况。如果出现一组中是\(-1,-1\)的情况,那就可以颠倒顺序,统计出可以颠倒顺序的组的数量\(p\),然后就可以知道对于当前回合的方案数\(cnt!\times2^p\),然后再递归的计算下一个回合即可。

#include <bits/stdc++.h>

using namespace std;

#define int long long

const int mod = 998244353;
vector<int> fact;

int power(int x, int y) {
    int ans = 1;
    while (y) {
        if (y & 1) ans = ans * x % mod;
        x = x % mod * x % mod, y >>= 1;
    }
    return ans;
}

int calc(int k, vector<int> a) {
    if (k == 0) return 1;
    int mid = 1ll << (k - 1);
    int cnt = 0, p = 0;

    vector<int> b(1, 0);
    for (int i = 1; i < a.size(); i += 2) {
        if (a[i] > a[i + 1])swap(a[i], a[i + 1]);
        if (a[i] == -1 && a[i + 1] == -1) cnt++, p++, b.push_back(-1);
        else if (a[i] != -1 && a[i + 1] == -1) {
            if (a[i] > mid) return 0;
            b.push_back(a[i]), cnt++;
        } else if (a[i] == -1 && a[i + 1] != -1) {
            if (a[i + 1] <= mid) b.push_back(a[i + 1]), cnt++;
            else b.push_back(-1);
        } else {
            if (a[i] > mid || a[i + 1] <= mid) return 0;
            b.push_back(a[i]);
        }
    }
    return fact[cnt] * power(2, p) % mod * calc(k - 1, b) % mod;
}

int32_t main() {
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int k, n;
    cin >> k, n = 1 << k;
    fact = vector<int>(n + 1);
    fact[0] = 1;
    for (int i = 1; i <= n; i++) fact[i] = fact[i - 1] * i % mod;
    vector<int> a(n + 1);
    for (int i = 1; i <= n; i++) cin >> a[i];
    cout << calc(k, a);
    return 0;
}

F. Editorial for Two

二分答案。枚举出时间后,通过优先队列可以计算出规定时间内前缀可以解决的数量和后缀可以解决的数量。然后后就可以求出最多可以解决的数量。

#include <bits/stdc++.h>

using namespace std;

#define int long long

int read() {
    int x = 0, f = 1, ch = getchar();
    while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
    if (ch == '-') f = -1, ch = getchar();
    while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x * f;
}

void solve() {
    int n = read(), k = read();
    vector<int> a(n);
    for (auto &i: a) i = read();

    auto check = [n, a, k](int x) {
        vector<int> b(n);
        priority_queue<int> q;
        int sum = 0;
        for (int i = 0; i < n; i++) {
            sum += a[i], q.push(a[i]);
            while( sum > x ) sum -= q.top() , q.pop();
            b[i] = q.size();
            if( b[i] >= k ) return true;
        }
        sum = 0 , q = priority_queue<int>();
        for( int i = n-1 ; i >= 0 ; i -- ){
            sum += a[i] , q.push(a[i]);
            while( sum > x ) sum -= q.top() , q.pop();
            if( i > 0 && q.size() + b[i-1] >= k) return true;
            else if( i == 0 && q.size() >= k ) return true;
        }
        return false;
    };

    int l = 0 , r = 1e18 , mid , res;
    while( l <= r ){
        mid = ( l + r ) >> 1;
        if( check(mid) ) res = mid , r = mid - 1;
        else l = mid + 1;
    }
    cout << res << "\n";
    return;
}

int32_t main() {
    for (int t = read(); t; t--) solve();
    return 0;
}