五月杂题记

又鸽了一个月。OwO

5.4

CF1969B

先考虑将相同颜色的缩成一块。这样,串一定是 010101...101010...,我们同时记录一个块内字符的个数,记为 \(len_i\)

题目要求将所有的一放在零的后面。

我们从第一个 \(1\) 块开始遍历,每次 \(i += 2\)。那么 \(i + 1\) 一定是 \(0\)。题目中的操作相当于将 \(1\) 块与一个 \(0\) 拼在一起,然后将 \(0\) 移至最前段,总共移 \(len_{i+1}\) 次到下一块 \(1\) 或末尾。

当我们移至下一块一后,两段一拼在了一起。后面便一起移动。那么我们当前操作的序列长为 \(\sum_{j=1}^i len_j \times col_j\),用个变量 \(now\) 记着就行。

每一完整的移动代价为 \((now+1)\times len_{i+1}\),答案累加即可。

点击查看代码
// Author : Lucky_Cloud
#include <bits/stdc++.h>
#define int long long
#define pii pair<int, int>
#define db double
using namespace std;

int read() {
    int res = 0, f = 1; char c = getchar();
    while (c < '0' || c > '9') {
        if (c == '-') f = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9') {
        res = (res << 1) + (res << 3) + (c ^ 48);
        c = getchar();
    }
    return f == -1 ? -res : res;
}

const int N = 2e5 + 5;
int t, len[N], cnt;
char s[N];

void solve() {
    scanf("%s", s + 1);
    int n = strlen(s + 1);
    for (int i = 1; i <= n + 1; ++i) len[i] = 0;
    len[cnt = 1] = 1;
    int p = 1;
    for (int i = 2; i <= n; ++i) {
        if (s[i] != s[p]) cnt++, p = i;
        len[cnt]++;
    }
    int be = 1;
    if (s[1] == '0') be++;
    int ans = 0;
    // cout << cnt << ' ' << be << ' ';
    int now = 0;
    for (int i = be; i <= cnt; i += 2) {
        now += len[i];
        ans += (now + 1) * len[i + 1];
    }
    cout << ans << endl;
}

signed main() {
    t = read();
    while (t--) solve();
    return 0;
}

CF1969C

考虑 DP。

\(f_{i,j}\) 表示前 \(i\) 个一共改了 \(j\) 次。

首先我们要知道:我们修改的话,最后一段的值是相同的。

  1. 若当前不改,\(f_{i,j}=f_{i-1,j}+a_i\)
  2. 当前修改,最后一段 \(k\sim i\)\(a_i\) 相同,或是在 \(k \sim i\)\(a_k\) 相同。方程见代码。
点击查看代码
// Author : Lucky_Cloud
#include <bits/stdc++.h>
#define int long long
#define pii pair<int, int>
#define db double
using namespace std;

int read() {
    int res = 0, f = 1; char c = getchar();
    while (c < '0' || c > '9') {
        if (c == '-') f = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9') {
        res = (res << 1) + (res << 3) + (c ^ 48);
        c = getchar();
    }
    return f == -1 ? -res : res;
}

const int N = 3e5 + 5;
int t, n, a[N], m;

int f[N][20];

void solve() {
    n = read(), m = read();
    for (int i = 1; i <= n; ++i) 
        a[i] = read();
        // f[i][0] = f[i - 1][0] + a[i];
    for (int i = 1; i <= n; ++i) {
        for (int j = 0; j <= m; ++j) {
            f[i][j] = f[i - 1][j] + a[i];
            for (int k = i - 1, l = j - 1; l >= 0 && k; --l, --k) {
                f[i][j] = min(f[k - 1][l] + (j - l + 1) * a[i], f[i][j]);
                f[i][j] = min(f[k][l] + (j - l) * a[k], f[i][j]);
            }
        }
    }
    int ans = 1e18;
    for (int i = 0; i <= m; ++i) ans = min(ans, f[n][i]);
    cout << ans << endl;
}

signed main() {
    t = read();
    while (t--) solve();
    return 0;

} 
posted @ 2024-05-05 20:33  lucky_cloud  阅读(9)  评论(0编辑  收藏  举报