备战蓝桥杯---刷二分与前缀和题

刷点题~

1.二分+多路归并算法

对于每一个技能,我们把它看成一个等差数列,我们把所有可能都放到一个集合里,排个序,取前m个大即可,现在考虑优化,假如m不是很大,我们直接用优先队列即可,但是这里m很大,于是我们考虑二分,我们二分一下第m位选什么-x,那么大于X的>=m个,大于x的<m个,这里x就有二分性质,当我们确定x,那么对于每一个等差数列,我们可以用O(1)求出来,因此复杂度为nlogn。

下面是AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=100010;
int n,m;
int a[N],b[N];
bool check(int mid){
    LL res=0;
    for(int i=0;i<n;i++){
        if(a[i]>=mid) res+=(a[i]-mid)/b[i]+1;
        
    }
    return res>=m;
}
int main(){
    cin>>n>>m;
    for(int i=0;i<n;i++) scanf("%d%d",&a[i],&b[i]);
    int l=0,r=1e6;
    while(l<r){
        int mid=(l+r+1)/2;
        if(check(mid)) l=mid;
        else r=mid-1;
    }
    LL res=0;
    LL cnt=0;
    for(int i=0;i<n;i++){
        if(a[i]>=r){
            int c=(a[i]-r)/b[i]+1;
            int end=a[i]-(c-1)*b[i];
            cnt+=c;//cnt计算了重复的,当它>m时减去多的R
            res+=(LL)(a[i]+end)*c/2;
        }
    }
    cout<<res-(cnt-m)*r;
}

2.

对于每一个数据,我们求出来满足[A/V](下取整)=B的v的范围,然后取交集即可。

我们考虑一下A/V与V的函数图像:

因此就可以二分了,vmin=A/V<=B的最小的V,vmax=A/V<=B-1的最小的V-1(当然不用二分用公式也可)

下面是公式:

A/V在【B,B+1)内,转一下可得V为【A/B,A/(B+1))即可。

3.前缀和

我们看最终情况,它是中间一段是画的,旁边两端是被摧毁的,画的长度是n/2的上取整,事实上,我们可以取到任意的该长度的区间,如何证明?

首先,我们任取该长度的区间,我们大致做一下对称:

先看看奇数长度,对于第一步,我们先话中间空余的,以后哪一端是要坏的我们选那一段,这样子就可以了。

对于偶数长度,第一步任取接下来跟奇数一样即可。

因此问题就是求某一区间的最大和,这个用前缀和即可

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值