Codeforces Round 934 (Div. 2)

Codeforces Round 934 (Div. 2)

A - Destroying Bridges

解题思路:

完全图每个点的连边数为n1

  • k<n1:都可到达。
  • kn1:将点1的边删完,只能呆在点1

代码:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
#define fi first
#define se second
using piii = pair<ll, pair<ll, ll>>;
const ll inf = 1ll << 60;
using ull = unsigned long long;
const int mod = 998244353;

void solve()
{
    int n, k;
    cin >> n >> k;
    if (k >= n - 1)
    {
        cout << 1 << endl;
    }
    else
    {
        cout << n << endl;
    }
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

B - Equal XOR

解题思路:

对于每个数字只有三种情况:

  • 只出现在(1,n)
  • 只出现在(n+1,2n)
  • 一个出现在(1,n),另一个出现在n+1,2n

前两种情况数目肯定是相同的。

我们先用前两种成对分别填入l,r中,不够的再用第三种补,整个过程都是同步的。

代码:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
#define fi first
#define se second
using piii = pair<ll, pair<ll, ll>>;
const ll inf = 1ll << 60;
using ull = unsigned long long;
const int mod = 998244353;

void solve()
{
    int n, k;
    cin >> n >> k;
    vector<int> a(2 * n + 2);
    for (int i = 1; i <= 2 * n; i++)
    {
        cin >> a[i];
    }
    vector<int> l, r;
    vector<int> vis(2 * n + 10);
    // 2, 3, 4
    for (int i = 1; i <= n; i++)
    {
        vis[a[i]] += 1;
    }
    for (int i = n + 1; i <= 2 * n; i++)
    {
        vis[a[i]] += 2;
    }
    vector<int> ls, rs, t;
    for (int i = 1; i <= n; i++)
    {
        if (vis[a[i]] == 3)
        {
            t.push_back(a[i]);
        }
        else if (vis[a[i]] == 2)
        {
            ls.push_back(a[i]);
        }
    }
    for (int i = n + 1; i <= 2 * n; i++)
    {
        if (vis[a[i]] == 4)
        {
            rs.push_back(a[i]);
        }
    }
    sort(ls.begin(), ls.end());
    ls.erase(unique(ls.begin(), ls.end()), ls.end());
    sort(rs.begin(), rs.end());
    rs.erase(unique(rs.begin(), rs.end()), rs.end());
    for (int i = 0; i < min(ls.size(), rs.size()) && l.size() < 2 * k; i++)
    {
        l.push_back(ls[i]);
        l.push_back(ls[i]);
        r.push_back(rs[i]);
        r.push_back(rs[i]);
    }
    for (int i = 0; i < t.size() && l.size() < 2 * k; i++)
    {
        l.push_back(t[i]);
        r.push_back(t[i]);
    }
    // int t1 = 0;
    // int t2 = 0;
    for (auto x : l)
    {
        cout << x << ' ';
        // t1 ^= x;
    }
    cout << "\n";
    for (auto x : r)
    {
        cout << x << ' ';
        // t2 ^= x;
    }
    cout << "\n";
    // if (t1 == t2)
    // {
    //     puts("YES");
    // }
    // // for (int i = 1; i <= n; i++)
    // // {
    // //     t1 ^= a[i];
    // // }
    // for (int i = n + 1; i <= 2 * n; i++)
    // {
    //     t2 ^= a[i];
    // }
    // cout << t1 << ' ' << t2 << endl;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

C - MEX Game 1

解题思路:

出现次数大于1次的,无论先后手肯定都能抢到。

所以我们按照mex,从小到大优先拿出现次数为1的。

代码:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
#define fi first
#define se second
using piii = pair<ll, pair<ll, ll>>;
const ll inf = 1ll << 60;
using ull = unsigned long long;
const int mod = 998244353;

void solve()
{
    int n;
    cin >> n;
    vector<int> a(n + 1);
    map<int, int> cnt;
    vector<bool> vis(n + 1);
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
        cnt[a[i]]++;
    }
    for (auto t : cnt)
    {
        if (t.se >= 2)
        {
            vis[t.fi] = true;
        }
    }
    int cur = 0;
    while (vis[cur])
    {
        cur++;
    }
    for (int i = 1; i <= n; i++)
    {
        while (vis[cur])
        {
            cur++;
        }
        if (cnt[cur] == 1)
        {
            cnt[cur]--;
            vis[cur] = true;
        }
        else
        {
            break;
        }
        while (vis[cur])
        {
            cur++;
        }
        if (cnt[cur] == 1)
        {
            cnt[cur]--;
        }
    }
    int ans = 0;
    while (vis[ans])
    {
        ans++;
    }
    cout << ans << endl;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

D - Non-Palindromic Substring

解题思路:

len=rl+1

  • k=1:肯定回文。
  • k=len:单独判断
  • 2klen1
    • k为奇数:只要整个区间不是aba...aba这种交叉形式,奇数子串一定都存在。如果k=3不存在,意味着整个区间都是aba...aba这种交叉形式。
    • k为偶数:只要整个区间字符不是都一样,偶数子串一定都存在。如果k=2不存在,意味着整个区间都是一样的。

注意:本题疑似卡了单哈希,如果要用哈希判断整体是否回文,建议使用双哈希映射。

判断整体回文:manacher;双哈希

判断奇数是否存在:

  • 思路一:f[i]:(f[l]r||f[l+1]r)
  • 思路二:哈希判断(l,r2)(l+2,r)是否完全相同。

判断偶数是否存在:

  • 思路一:f[i]:(f[l]r)
  • 思路二:区间最大最小值相同。

代码:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<ll, ll>;
#define fi first
#define se second
using piii = pair<ll, pair<ll, ll>>;
const ll inf = 1ll << 60;
using ull = unsigned long long;
const int P = 13331;
std::vector<int> manacher(std::string s)
{
    std::string t = "#";
    for (auto c : s)
    {
        t += c;
        t += '#';
    }
    int n = t.size();
    std::vector<int> r(n);
    for (int i = 0, j = 0; i < n; i++)
    {
        if (2 * j - i >= 0 && j + r[j] > i)
        {
            r[i] = std::min(r[2 * j - i], j + r[j] - i);
        }
        while (i - r[i] >= 0 && i + r[i] < n && t[i - r[i]] == t[i + r[i]])
        {
            r[i] += 1;
        }
        if (i + r[i] > j + r[j])
        {
            j = i;
        }
    }
    return r;
}

void solve()
{
    int n, q;
    cin >> n >> q;
    string s;
    cin >> s;
    auto rad = manacher(s);
    string str = s;
    s = ' ' + s;
    vector<ull> h(n + 1), p(n + 1), h1(n + 10);
    p[0] = 1;
    for (int i = 1; i <= n; i++)
    {
        p[i] = p[i - 1] * P;
        h[i] = h[i - 1] * P + s[i];
    }
    reverse(str.begin(), str.end());
    str = ' ' + str;
    for (int i = 1; i <= n; i++)
    {
        h1[i] = h1[i - 1] * P + str[i];
    }
    auto get1 = [&](int l, int r) -> ull
    {
        return h[r] - h[l - 1] * p[r - l + 1];
    };
    auto get2 = [&](int l, int r) -> ull
    {
        return h1[r] - h1[l - 1] * p[r - l + 1];
    };
    vector<vector<int>> f(n + 1, vector<int>(22)), g(n + 1, vector<int>(22, 1e9));
    for (int j = 0; (1 << j) <= n; j++)
    {
        for (int i = 1; i + (1 << j) - 1 <= n; i++)
        {
            if (j == 0)
            {
                f[i][j] = s[i];
            }
            else
            {
                f[i][j] = max(f[i][j - 1], f[i + (1 << j - 1)][j - 1]);
            }
        }
    }
    auto q1 = [&](int l, int r)
    {
        int len = (r - l + 1);
        int k = log(len) / log(2);
        return max(f[l][k], f[r - (1 << k) + 1][k]);
    };
    for (int j = 0; (1 << j) <= n; j++)
    {
        for (int i = 1; i + (1 << j) - 1 <= n; i++)
        {
            if (j == 0)
            {
                g[i][j] = s[i];
            }
            else
            {
                g[i][j] = min(g[i][j - 1], g[i + (1 << j - 1)][j - 1]);
            }
        }
    }
    auto q2 = [&](int l, int r)
    {
        int len = (r - l + 1);
        int k = log(len) / log(2);
        return min(g[l][k], g[r - (1 << k) + 1][k]);
    };

    while (q--)
    {
        int l, r;
        cin >> l >> r;
        ll len = r - l + 1;
        ll ans = 0;
        // if (len & 1)
        // {
        //     ll t = len / 2;
        //     if (get1(l, l + t - 1) != get2(n - r + 1, n - (l + t + 1) + 1))
        //     {
        //         ans += len;
        //     }
        // }
        // else
        // {
        //     ll t = len / 2;
        //     if (get1(l, l + t - 1) != get2(n - r + 1, n - (l + t) + 1))
        //     {
        //         ans += len;
        //     }
        // }
        // cout << ans << endl;
        if (rad[l + r - 1] <= len)
        {
            ans += len;
        }
        if (q1(l, r) != q2(l, r))
        {
            ll up = len;
            if (len & 1)
            {
                up--;
            }
            else
            {
                up -= 2;
            }
            ll k = up / 2;
            ans += (2 + up) * k / 2;
        }
        if (len > 3 && get1(l, r - 2) != get1(l + 2, r))
        {
            ll up = len;
            if (len & 1)
            {
                up -= 2;
            }
            else
            {
                up--;
            }
            ll k = up / 2;
            ans += (3 + up) * k / 2;
        }
        cout << ans << "\n";
    }
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t = 1;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}
posted @   value0  阅读(402)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
点击右上角即可分享
微信分享提示