Educational Codeforces Round 160 (Rated for Div. 2)

Educational Codeforces Round 160 (Rated for Div. 2)

A - Rating Increase

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
typedef pair<ll, ll> pii;
#define fi first
#define se second

void solve()
{
    string s;
    cin >> s;
    int n = s.size();
    bool f = false;
    string a, b;
    for (int i = 1; i < n; i++)
    {
        if (s[i] != '0')
        {
            a = s.substr(0, i);
            b = s.substr(i);
            ll x = strtoll(a.c_str(), NULL, 10);
            ll y = strtoll(b.c_str(), NULL, 10);
            if (x < y)
            {
                f = true;
                break;
            }
        }
    }
    if (f)
    {
        cout << a << ' ' << b << endl;
    }
    else
    {
        puts("-1");
    }
}

int main()
{
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

B - Swap and Delete

解题思路:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
typedef pair<ll, ll> pii;
#define fi first
#define se second

void solve()
{
    string s;
    cin >> s;
    int a = 0;
    int b = 0;
    int n = s.size();
    vector<int> pre0(n + 1), pre1(n + 1);
    s = ' ' + s;
    for (int i = 1; i <= n; i++)
    {
        if (s[i] == '0')
        {
            a++;
            pre0[i] = pre0[i - 1] + 1;
            pre1[i] = pre1[i - 1];
        }
        else
        {
            b++;
            pre0[i] = pre0[i - 1];
            pre1[i] = pre1[i - 1] + 1;
        }
    }
    if (a == pre1[n] && b == pre0[n])
    {
        cout << 0 << endl;
    }
    else
    {
        int cur = n;
        while (true)
        {
            bool f = false;
            while (cur > 0 && pre0[cur] < b)
            {
                cur--;
                b--;
                if (pre1[cur] == a && pre0[cur] == b)
                {
                    f = true;
                    break;
                }
            }
            while (cur > 0 && pre1[cur] < a)
            {
                cur--;
                a--;
                if (pre1[cur] == a && pre0[cur] == b)
                {
                    f = true;
                    break;
                }
            }
            if (f)
            {
                break;
            }
        }
        cout << n - cur << endl;
    }
}

int main()
{
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

C - Game with Multiset

解题思路:

记录每一个二进制数位有多少个,从低位向高位实时转换。

代码:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
#define fi first
#define se second
using i128 = __int128_t;
using piii = pair<ll, pair<ll, ll>>;

void solve()
{
    vector<int> cnt(40, 0);
    int n;
    cin >> n;
    while (n--)
    {
        int t, x;
        cin >> t >> x;
        if (t == 1)
        {
            cnt[x]++;
        }
        else
        {
            int cur = 0;
            for (int i = 0; i <= 30; i++)
            {
                cur += cnt[i];
                if (x >> i & 1)
                {
                    if (cur > 0)
                    {
                        x -= 1 << i;
                        cur--;
                    }
                    else
                    {
                        break;
                    }
                }
                cur /= 2;
            }
            if (x)
            {
                puts("NO");
            }
            else
            {
                puts("YES");
            }
        }
    }
}

int main()
{
    int t = 1;
    // cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

D - Array Collapse

解题思路:

\(dp1[i]:考虑前i个数,以a[i]为最后一个数的方案数\)

\(dp2[i]:考虑前i个数,删去a[i]的方案数\)

\(dp1[i]\)考虑从\(dp1[1, i -1]\)转移过来。我们发现,对于\(a[i]\)最多删到前面第一个比他小的数字,设该数字下标为\(idx\).

对于\(dp1[idx, i-1]\): \(dp1[i] = dp1[i] + \sum\limits_{j = idx}^{i-1}dp1[j]\)

对于\(dp1[1,idx -1]\):\(dp1[i] = dp1[i] + dp2[idx]\)

代码:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
#define fi first
#define se second
using i128 = __int128_t;
using piii = pair<ll, pair<ll, ll>>;
const int mod = 998244353;
void solve()
{
    int n;
    cin >> n;
    vector<int> a(n + 1);
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
    }
    // dp1[i]:考虑前i个数,以a[i]为最后一个数的方案数
    // dp2[i]:考虑前i个数,删去a[i]的方案数
    vector<ll> dp1(n + 1), dp2(n + 1), pre(n + 1);
    vector<int> q(n + 1);
    int hh = 0;
    int tt = -1;
    dp1[1] = 1;
    pre[1] = 1;
    q[++tt] = 1;
    for (int i = 2; i <= n; i++)
    {
        while (hh <= tt && a[q[tt]] >= a[i])
        {
            tt--;
        }
        if (hh <= tt)
        {
            int idx = q[tt];
            // 从(idx ~ i - 1)不同结尾转移而来 + 与idx前面的结尾链接
            dp1[i] = ((pre[i - 1] - pre[idx - 1]) % mod + mod) % mod + dp2[idx];
            // 前面第一个小于自己的值消掉自己 + 跟前面存在的更小值消掉自己
            dp2[i] = dp1[idx] + dp2[idx];
        }
        else
        {
            // 必须保留,没法删掉
            // +1是把前面全删了
            dp1[i] = (pre[i - 1] + 1) % mod + mod;
            dp2[i] = 0;
        }
        dp1[i] %= mod;
        dp2[i] %= mod;
        pre[i] = (pre[i - 1] + dp1[i]) % mod;
        q[++tt] = i;
    }
    ll ans = (dp1[n] + dp2[n]) % mod;
    cout << ans << endl;
}

int main()
{
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}
posted @ 2024-02-29 09:59  value0  阅读(20)  评论(0)    收藏  举报