1 条题解

  • 0
    @ 2026-10-31 17:58:20

    思路

    观察:

    • 能量核心被分成若干个「段」,每段由连续的非零元素组成(段与段之间由零隔开);
    • 每个包含核心的连续段必须至少手动激活一个核心,之后连锁反应会把该段内所有核心全部激活;
    • 因此对每一段,最优策略就是手动激活该段中消耗最少的那个核心,该段花费等于段内最小值;
    • 不同段之间互不影响,总消耗 = 所有段的最小值之和。

    实现:

    1. 边读入边处理:维护当前段的最小值 mi;
    2. 遇到 00:当前段结束,把 mi 累加进总消耗,并把 mi 重置为「无穷大」(若此前没有非零元素则段为空,加 00);
    3. 遇到非零元素:用 min(mi, x) 更新当前段最小值;
    4. 数组读完后还要再结算一次最后一段,避免漏掉结尾不是零的段。

    边界: 全为 00 时没有任何段,答案为 00;mi==inf 的判断正是用来跳过空段。

    复杂度: 每个测试用例时间 O(n)O(n)(多组数据合计 O(∑n)O(\sum n)),额外空间 O(1)O(1)。

    代码

    #include<bits/stdc++.h>
    #define int long long
    #define dd double
    #define str string
    #define el cout << '\n'
    #define re return
    #define ff first
    #define ss second
    #define pll pair<int,int>
    #define pdd pair<dd,dd>
    #define all(x) x.begin(),x.end()
    #define pb push_back
    using namespace std;
    
    void go(){
        int n;cin>>n;
        int inf = 1e18;
        int tot = 0, mi = inf;           // tot 总消耗,mi 当前段的最小值
    
        for(int i=1;i<=n;i++){
            int x;cin>>x;
            if(x==0){
                // 遇到 0,当前段结束:累加段内最小值;空段(mi 仍为 inf)加 0
                tot += (mi==inf?0:mi);
                mi = inf;                // 重置,开始下一段
            }else{
                mi = min(mi, x);         // 维护当前段的最小消耗
            }
        }
        // 结算最后一段(数组以非零元素结尾时不会被上面的 0 触发)
        tot += (mi==inf?0:mi);
    
        cout<<tot<<endl;
    }
    
    signed main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);cout.tie(nullptr);
        int _=1;
        cin >>_;                         // 多组测试数据
        while(_--){
            go();
        }
        return 0;
    }
    
    • 1

    信息

    ID
    36
    时间
    1000ms
    内存
    256MiB
    难度
    4
    标签
    递交数
    0
    已通过
    0
    上传者