lq 集训第二天 (第一天习题部分)

提示:仅供参考


题目


一、分析


题目问的是最多的鸭鸭数量,也就是1的数量。首先我们不考虑魔法的使用,那么总重量应该就是所有编号为1的a[i]的重量相加,我们将这个命名为 ess(essential的缩写)作为基本量。然后对整个数组进行修改。

我们知道 在一段区间内进行修改,0 变为 1 的话会让 ess 增加,但是区间内会有1 变为 0 的情况 ,也就是可能有的鸭鸭会变成鼠鼠,那么就会让 ess 减少,对于一段区间内的变化,我们很容易想到刚学习过的前缀和知识,而且这是一维的,所以很简单。但是对于1变成 0 的情况,我们需要将其变为负数。对于样例二,也就是将原数组对应的1的5需要处理成-5。这样就完成了数组的处理,再进行前缀和,我们知道了任意区间长度的和,如果是正的,很明显可以增加鸭鸭的数量。

那么,我们就把问题转化为了求子区间和的最大值,这里我有两种算法(实际上还有很多),一种是贪心算法,一种是枚举r。对于贪心算法,我们采取的策略是,从头开始对处理后的原数组进行逐次增加,如果加到和为负数的时候,那么我们就舍弃掉这段,在下一个位置重新从零开始记录。代码留给大家思考,我在第三天的篇章开头给出答案。 对于枚举r,在每个情况内,prefix[r]是确定的,那么为了fix偏移量最大,那么就要求prefix[l - 1]最小,那么在遍历过程中进行存储即可。


二、代码展示

代码如下:

#include<bits/stdc++.h>

using namespace std;

using ll = long long;

const int N = 1e5 + 10;

ll a[N],w[N],p[N];
int T;


void solve()
{
    int n; 
    cin >> n;
    for(int i = 1; i <= n; i ++) cin >> a[i];
    for(int i = 1; i <= n; i ++) cin >> w[i];
    
    ll fix = 0, ess = 0, mi = 0;
    for(int i = 1; i <= n; i ++) ess += a[i] * w[i];
    
    for(int i = 1; i <= n; i ++)
    {
        p[i] = p[i - 1] + (a[i] ? -1 : 1) * w[i];
        fix = max(fix , p[i] - mi);
        mi = min(mi, p[i]);
    }
    
    cout << ess + fix << '\n';
}
int main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin >> T;
    while(T --) solve();
    return 0;
}

总结

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值