寒假思维训练计划day4

文章讲述了如何通过贪心算法解决Codeforces中的一个问题,即在给定数组中找到最优方式将其分成连续块,使得所有子数组代价之和最大。作者强调了倒序考虑和贪心决策的重要性,以及代码实现的简化过程。
摘要由CSDN通过智能技术生成

又来还债啦,每日一更,今天两更。

又是一道经典的构造题,前些日子只顾刷题,懒写题解,以前欠的债现在还...(也当做是回顾
​
题意:
给定一个长度为n的数组,要求将数组分成若干个(>=1)连续的块,使得所有子数组的代价之和最大,代价的计算:
[x1,x2,x3],[x4,x5,x6]的计算方法是:(x1+x2+x3)*1 + (x4+x5+x6)*2,也就是sum*i
题解:
这道题要倒着贪,考虑当前i这个位置,后缀和sum + a[i] > 0的时候在此位置分块,后面至少要分>=0的块,此时一定是正的贡献,无论后面是分/不分结果都更好,如果sum + a[i] <= 0的时候此时应该尽量少的加块,从前往后去合并知道sum + a[j] > 0,最后算出答案。

代码:建议只看solve(),主要是贪心策略的去确定,实现起来还是很简单的;

// cpp代码:
#include <bits/stdc++.h>
#define int long long 
using namespace std; 
const int N = 2e5 + 10; 
int n, m; 
int a[N];
void solve() {
    cin >> n;
    int ans = 0;
    for(int i = 1; i <= n; i ++ ) cin >> a[i], ans += a[i] * i;
    int lsum = 0, cnt = 1, res = 0; 
    vector<int> us; 
    a[n + 1] = 0; 
    for(int i = n,j,s; i >= 1; i -- ) { 
        lsum += a[i]; 
        if(lsum <= 0) {
            j = i, s = a[i]; 
            while(j - 1 >= 1 && lsum <= 0) s += a[j - 1], lsum += a[j - 1], -- j;
            us.push_back(s);
            i = j;
        }
        else us.push_back(a[i]); 
    }
    for(int i = us.size() - 1; i >= 0; i -- ) {
        // cout << us[i] << endl; 
        res += us[i] * cnt ++; 
    }
    cout << max(res,ans) << endl; 
}
signed main() { 
    int ts; 
    cin >> ts;
    while(ts--) solve(); 
    
    return 0;
}	
 

  • 15
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嘗_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值