专栏文章

题解:P12350 「HCOI-R2」光影

P12350题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@mipf7dtm
此快照首次捕获于
2025/12/03 11:01
3 个月前
此快照最后确认于
2025/12/03 11:01
3 个月前
查看原文

思路

大意:为了将尽可能多的 1(分散的)合并成尽可能少的“块”。
St{S_{t}} 表示 t{t}t+1{t+1} (两个 1)之间所有 0 的个数。如果 k>SA>SB{k>S_{A}>S_{B}},那么删除区间 [B,B+1]{[B,B+1]} 会比删除 [A,A+1]{[A,A+1]} 要优。
首先,将所有 1 的位置找出来,将索引放入 Lkd 中。
其次,计算每一个 Sti{S_{t_{i}}},排序。 最后,照题意,从小到大删除 0,然后输出。

代码

CPP
#include <bits/stdc++.h>
using namespace std;

int main() {
    int n, k;
    scanf("%d%d", &n, &k);
    vector<int> ones; // 存储所有 '1' 的位置

    // 读取输入并记录 '1' 的位置
    for (int i = 0; i < n; ++i) {
        char c;
        scanf(" %c", &c);
        if (c == '1') ones.push_back(i);
    }

    if (ones.empty()) { // 没有 '1' 的情况
        printf("0\n");
        return 0;
    }

    // 计算初始块数:连续的 '1' 视为一个块
    int initial_ones = 1;
    for (int i = 1; i < ones.size(); ++i) {
        if (ones[i] != ones[i-1] + 1) initial_ones++;
    }

    // 计算相邻块之间的间隙
    vector<int> gaps;
    int prev_end = ones[0]; // 前一个块的最后一个 '1' 的位置
    for (int i = 1; i < ones.size(); ++i) {
        if (ones[i] != ones[i-1] + 1) { // 发现新块
            int gap = ones[i] - prev_end - 1;
            if (gap > 0) gaps.push_back(gap);
            prev_end = ones[i];
        } else {
            prev_end = ones[i]; // 同一块内,更新末尾位置
        }
    }

    sort(gaps.begin(), gaps.end()); // 按间隙大小排序

    // 贪心合并:优先删除小间隙
    int merge_cnt = 0;
    for (int g : gaps) {
        if (k >= g) {
            k -= g;
            merge_cnt++;
        } else break;
    }

    printf("%d\n", initial_ones - merge_cnt);
    return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...