1. 程式人生 > 實用技巧 >Codeforces Global Round 12

Codeforces Global Round 12

A - Avoid Trygub

int main() {
    IOS;
    for (cin >> _; _; --_) {
        string s; cin >> n >> s;
        sort(all(s)); cout << s << '\n';
    }
    return 0;
}

B - Balls of Steel

列舉找就完事

PII a[N];
 
int main() {
    IOS;
    for (cin >> _; _; --_) {
        cin >> n >> k;
        rep (i, 1, n) cin >> a[i].fi >> a[i].se;
        int ans = -1;
        rep (i, 1, n) {
            bool f = 0;
            rep (j, 1, n) if (abs(a[i].fi - a[j].fi) + abs(a[i].se - a[j].se) > k) { f = 1; break; }
            if (!f) { ans = 1; break; }
        }
        cout << ans << '\n';
    }
    return 0;
}

C1 & C2 - Errich-Tac-Toe

明顯是考慮(i + j) % 3, 記 ++cnt[(i + j) % 3][s[i][j] == 'X']

最後無非選擇 i, j(-1<i,j<3, i!=j) 使得 s[i][1] + s[j][0] <= k/3, 即使得每3個相鄰的標記中存在兩個不同的標記

一定存在這樣的 i, j使得 <= k/3, 自己畫個表就明白了

int main() {
    IOS;
    for (cin >> _; _; --_) {
        cin >> n; memset(c, 0, sizeof c);
        rep (i, 0, n - 1) {
            cin >> s[i];
            rep (j, 0, n - 1) if (s[i][j] != '.') ++c[(i + j) % 3][s[i][j] == 'X'], ++k;
        }
        rep (i, 0, 2) rep (j, 0, 2) if (i != j && c[i][1] + c[j][0] <= k / 3) {
            rep (x, 0, n - 1) rep (y, 0, n - 1) if (s[x][y] != '.')
                if ((x + y) % 3 == i) s[x][y] = 'O';
                else if ((x + y) % 3 == j) s[x][y] = 'X';
            k = 0;
        }
        rep (i, 0, n - 1) cout << s[i] << '\n';
    }
    return 0;
}

D - Rating Compression

md, 向獲取 a[i] 能被選出來的範圍 l~r, 用了線段樹+倍增 t7

直接單調棧不好嗎? 不過cf \(nlog^2n\) 常數稍大點竟然過不去, 離譜

nt a[N], b[N], l[N];
 
int main() {
    IOS;
    for (cin >> _; _; --_) {
        cin >> n;
        rep(i, 1, n) cin >> a[i], b[i] = 0;
        stack<PII> q;
        rep(i, 1, n) {
            while (!q.empty() && q.top().fi >= a[i]) umax(b[q.top().fi], i - l[q.top().se]), q.pop();
            if (q.empty()) l[i] = 1;
            else l[i] = q.top().se + 1;
            q.push({ a[i], i });
        }
        while (!q.empty()) umax(b[q.top().fi], n + 1 - l[q.top().se]), q.pop();
        rep(i, 2, n) umin(b[i], b[i - 1]);
        rep(i, 1, n) cout << (b[n - i + 1] >= i); cout << '\n';
    }
    return 0;
}

F - The Struggling Contestant

先把-1考慮了, 無非是某個數多餘 (n + 1) / 2

然後是將序列分段, 記錄每個數作為端點必須要出現的次數

比如 1 2 2 3 4 5, 對於2來說, a[2]於a[3]要隔開,並且這兩個數要作為切割後的序列的端點(前端和後端)

對於 1, 5, 本來就是端點, 直接+1, 最後就是端點之間的相互拼接, 不過拼接的兩個端點不能是相同的數,

你不能那端點 a[2] 和 a[3] 拼接, 但可以 a[2] 和 a[1]/a[6] 拼接, 既然都是端點了, 肯定貪心的先和其他端點拼接

最後如果存在 沒有拼接的端點, 紀要使用那些單點了,

es 1 2 2 2 2 3 4, a[2] a[1] a[3] a[6] a[7] a[4] a[5] a[6]

當前剩下端點 a[4] 和 a[5], 只好使用 a[6] 去分割了 2 1 2 4 2 3 2

答案也就是 k + max(0, \(max_f[x]\) - k - 2), f[i] 表示 i 作為端點的數量, k是相鄰端點的數量

int main() {
    IOS;
    for (cin >> _; _; --_) {
        cin >> n; VI a(n + 1), cnt(n + 1), f(n + 1); k = 0;
        rep (i, 1, n) {
            cin >> a[i]; ++cnt[a[i]];
            if (i > 1 && a[i] == a[i - 1]) f[a[i]] += 2, ++k;
        }
        if (*max_element(all(cnt)) > (n + 1) / 2) { cout << "-1\n"; continue; }
        ++f[a[1]], ++f[a[n]];
        cout << k + max(0, *max_element(all(f)) - k - 2) << '\n';
    }
    return 0;
}