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;
}

E - Capitalism

建图跑个多源最短路就好,

b = 1, d[u][v] = 1, d[v][u] = -1;

b = 0, d[u][v] = d[v][u] = 1;

分别跑出来以 i 为最少的资本, 的最短路

找到以谁为起点s, 差值最大就行

判 no, 就对于 d[s][u] == d[s][v] 为 no 就行

顺便用 d[i][i] 判个负环

int d[N][N];

int main() {
    IOS; cin >> n >> m; vector<pair<PII, int>> e(m);
    rep (i, 1, n) rep (j, 1, n) d[i][j] = i == j ? 0 : inf;
    for (auto &i : e) {
        cin >> i.fi.fi >> i.fi.se >> i.se;
        d[i.fi.fi][i.fi.se] = 1;
        d[i.fi.se][i.fi.fi] = i.se ? -1 : 1;
    }
    rep (k, 1, n) rep (i, 1, n) rep (j, 1, n) umin(d[i][j], d[i][k] + d[k][j]);
    int mx = -1, w;
    rep (i, 1, n) {
        if (d[i][i] < 0) { cout << "NO"; return 0; }
        for (auto &j : e) if (d[i][j.fi.fi] == d[i][j.fi.se]) { cout << "NO"; return 0; }
        rep (j, 1, n) if (d[i][j] > mx) mx = d[i][j], w = i; 
    }
    cout << "YES\n" << mx << '\n';
    rep (i, 1, n) cout << d[w][i] << ' ';
    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是相邻端点的数量

简单来说 k, 是必须要所示的贡献, 两个相邻的相同的数, 拆入一个数, 最少贡献 +1, 1 2 2 -> 2 1 2 贡献为1

然后是相互插入 2 2 2 3 3 -> 2 3 2 3 2, 没贡献, 2 2 2 2 3 3 4 -> 2 3 2 3 2 4 2, 额外使用了单点 a[7], 贡献+1

1 2 2 2 3 3 4 4 4 5 -> 1 2 3 4 2 3 4 2 4 5, 无额外贡献, 说白了就是看那个最多的数作为端点其他数能不能将这个完全分割

为啥是 max(0, \(max_f[x]\) - k - 2) 要减个2? 你把那个最多的点作为整个序列的前后端点, 不挨着其他数

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;
}
posted @ 2020-12-07 12:05  洛绫璃  阅读(644)  评论(5编辑  收藏  举报