Educational Codeforces Round 105 (Rated for Div. 2)

Educational Codeforces Round 105 (Rated for Div. 2)

A - ABC String

第一个字母只能是 '(', 最后一个字母不等于第一个字母且只能是 ')'

所以就剩下一个字母没确定, 直接分情况讨论两边即可

int a[3], x[2], y[2];
 
int main() {
    IOS;
    for (cin >> _; _; --_) {
        string s; cin >> s; bool f = 1, g = 1;
        memset(a, -1, sizeof a); rep (i, 0, 1) x[i] = y[i] = 0; 
        if (s[0] == s.back()) { cout << "NO
"; continue; }
        a[s[0] - 'A'] = 0; a[s.back() - 'A'] = 1;
        for (auto &i : s) {
            if (a[i - 'A'] != -1) ++x[a[i - 'A']], ++y[a[i - 'A']];
            else ++x[0], ++y[1];
            if (x[0] < x[1]) f = 0;
            if (y[0] < y[1]) g = 0;
        }
        if (f && x[0] == x[1]) cout << "YES
";
        else if (g && y[0] == y[1]) cout << "YES
";
        else cout << "NO
";
    }
    return 0;
}

B - Berland Crossword

状压枚举四个角有没有黑块

int a[5], b[5];
 
int main() {
    IOS;
    for (cin >> _; _; --_) {
        cin >> n; rep (i, 1, 4) cin >> a[i]; bool f = 0;
        rep (i, 0, (1 << 4) - 1) {
            rep (i, 1, 4) b[i] = a[i];
            if (i & 1) --b[1], --b[4];
            if (i >> 1 & 1) --b[1], --b[2];
            if (i >> 2 & 1) --b[2], --b[3];
            if (i >> 3 & 1) --b[3], --b[4];
            bool g = 1;
            rep (i, 1, 4) if (b[i] < 0 || b[i] > n - 2) g = 0;
            f = f || g;
        }
        cout << (f ? "YES
" : "NO
");
    }
    return 0;
}

C - 1D Sokoban

直接正负对称, 直接把负数 reverse, 在取反, 就是两次相同的过程

然后就是模拟推箱子取max即可

ll a[N], b[N];
 
int work(int x, int y, int n, int m) {
    int ans = 0, res = 0; unordered_set<ll> st;
    rep (i, y, m) st.insert(b[i]);
    rep (i, x, n) if (st.count(a[i])) ++res; ans = res;
    for (int i = x, j = y, k = y; i <= n && j <= m; ++i) {
        if (st.count(a[i])) --res;
        while (j <= m && b[j] <= a[i]) ++j;
        for (; j <= m && ((i < n && b[j] < a[i + 1]) || i == n); ++j) {
            while (b[j] - b[k] > i - x) ++k;
            umax(ans, res + min(j - k + 1, i - x + 1));
        }
    }
    return ans;
}
 
int main() {
    IOS;
    for (cin >> _; _; --_) {
        cin >> n >> m; int x = n + 1, y = m + 1; a[0] = b[0] = -1;
        rep (i, 1, n) { cin >> a[i]; if (a[i - 1] * a[i] < 0) x = i; }
        rep (i, 1, m) { cin >> b[i]; if (b[i - 1] * b[i] < 0) y = i; }
        reverse(a + 1, a + x); reverse(b + 1, b + y);
        rep (i, 1, x - 1) a[i] = -a[i];
        rep (i, 1, y - 1) b[i] = -b[i];
        cout << work(x, y, n, m) + work(1, 1, x - 1, y - 1) << '
';
    }
    return 0;
}

D - Dogeforces

好气, 没输出总经理, 最后没时间改了, 艹, B卡太长时间了, 各种枚举情况, 直接状压枚举不就好了.... 暴力都不会

贪心, 为了防止有的经理没有两个下属, 尽量多添加经理, 比如 a[i][j] = a[x][y] = c, 直接 i,j 从属 e, x,y 从属 e,

而不是 i,j,x,y 从属于一个经理, 导致最后 i,j,x,y的上上级只有 i,j,x,y 的上级 这一个下属

从低到高枚举工资, 并查集添加经理即可, 还是模拟, 最坏情况就是每两个员工有个经理, 成线段树的空间棵 N * 4

vector<PII> h[N * 10];
int b[N << 2], f[N << 4], a[N << 4], fa[N << 4];
 
int find(int x) { return x == f[x] ? x : f[x] = find(f[x]); }
 
int main() {
    IOS; cin >> n; k = n; int mx = 0;
    rep(i, 1, n) f[i] = i;
    rep(i, 1, n) rep(j, 1, n) {
        cin >> m;
        if (i == j) b[i] = m;
        else if (i < j) h[m].pb(i, j), umax(mx, m);
    }
    rep(i, 1, mx - 1) {
        if (h[i].empty()) continue;
        int cur = k;
        for (auto& j : h[i]) fa[j.fi] = find(j.fi), fa[j.se] = find(j.se);
        for (auto& j : h[i]) f[find(fa[j.fi])] = find(fa[j.se]);
        for (auto& j : h[i]) {
            int x = find(j.fi);
            if (x <= cur) b[++k] = i, f[x] = f[k] = k, x = k;
            a[fa[j.fi]] = a[fa[j.se]] = x;
        }
    } b[++k] = mx;
    for (auto& i : h[mx]) a[find(i.fi)] = a[find(i.se)] = k;
    cout << k << '
';
    rep(i, 1, k) cout << b[i] << ' '; cout << '
';
    cout << k << '
';
    rep(i, 1, k - 1) cout << i << ' ' << a[i] << '
';
    return 0;
}

E - A-Z Graph

忘了和哪一次了, 差不多, 让你选奇数和偶数的回文对称路径,

这道比那道还简单, 为偶数有两个点存在边且字符相同 yes, 为奇数, 两个点互相有边即可

unordered_map<int, char> h[N];

int main() {
    IOS; cin >> n >> m; int x = 0, y = 0;
    rep (i, 1, m) {
        char op; cin >> op;
        if (op == '+') {
            int u, v; char c; cin >> u >> v >> c;
            h[u][v] = c;
            auto it = h[v].find(u);
            if (it != h[v].end() && it->se == c) ++x;
            if (it != h[v].end()) ++y;
        } else if (op == '-') {
            int u, v; cin >> u >> v;
            auto aa = h[u].find(v), it = h[v].find(u);
            if (it != h[v].end() && it->se == aa->se) --x;
            if (it != h[v].end()) --y;
            h[u].erase(aa);
        } else {
            int k; cin >> k;
            if (k & 1) cout << (y ? "YES
" : "NO
");
            else cout << (x ? "YES
" : "NO
");
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/2aptx4869/p/14473025.html