二分大法

本文介绍了洛谷1月月赛中的一道算法题,涉及区间加法和乘法操作,目标是找到最大化区间和的方法。通过枚举乘法操作次数并使用二分查找优化加法操作,最终达到O(n log^2 n)的时间复杂度。博客还分享了一个小技巧,即在处理大整数乘法时可以使用__int128类型。
摘要由CSDN通过智能技术生成

洛谷1月月赛
A.「EZEC-5」魔法(签到题)

题意:(自己看)
思路:要使区间和最大,显然是先操作加法,然后操作乘法,且每次操作肯定直接操作整个区间即可。直接暴力枚举乘法次数,log的复杂度,然后加法满足二分又一个log的复杂度,check用求最大子段和O(n)
复杂度为 n l o g 2 n nlog^2 n nlog2n
小结:有两种操作方法时,可以枚举一个,另一个二分枚举,求满足题意的最值
一个没用的 小知识: 两个long long相乘时,可用__int128 定义他们

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f3f3f3f3f;
const int maxn=1e5+5;
ll n,a,b,s,dp[maxn],p[maxn],ans=inf ,base[maxn];
bool check(int tot1,int tot2){
    __int128 sum=0,ma=0; //用__int128 因为可能两个ll相乘
    for(int j=1;j<=n;j++){
        sum+=p[j]+tot2;
        if(sum<0){
            sum=0;
        }
        ma=max(ma,sum);
    }
    ma=ma*base[tot1];
    return ma>=s;
}
int main(){
	base[0]=1;
    for(int i=1;i<=40;i++){
        base[i]=base[i-1]*2;
    }
	scanf("%lld%lld%lld%lld",&n,&a,&b,&s);
	for(int i=1;i<=n;i++)
	    scanf("%lld",&p[i]);
	ll mb=log2(s)+1;
	for(ll i=0;i<=mb;i++){
		ll l=0,r=2e9,now=-1;
		while(l<=r){
			int mid=(l+r)>>1;
			if(check(i,mid)){
				now=mid,r=mid-1;
			}
			else l=mid+1;
		}
		if(now!=-1)
		ans=min(ans,now*a+i*b);
	}
	printf("%lld\n",ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值