当前位置:   article > 正文

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

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

刷点题~

1.二分+多路归并算法

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

下面是AC代码:

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. typedef long long LL;
  4. const int N=100010;
  5. int n,m;
  6. int a[N],b[N];
  7. bool check(int mid){
  8. LL res=0;
  9. for(int i=0;i<n;i++){
  10. if(a[i]>=mid) res+=(a[i]-mid)/b[i]+1;
  11. }
  12. return res>=m;
  13. }
  14. int main(){
  15. cin>>n>>m;
  16. for(int i=0;i<n;i++) scanf("%d%d",&a[i],&b[i]);
  17. int l=0,r=1e6;
  18. while(l<r){
  19. int mid=(l+r+1)/2;
  20. if(check(mid)) l=mid;
  21. else r=mid-1;
  22. }
  23. LL res=0;
  24. LL cnt=0;
  25. for(int i=0;i<n;i++){
  26. if(a[i]>=r){
  27. int c=(a[i]-r)/b[i]+1;
  28. int end=a[i]-(c-1)*b[i];
  29. cnt+=c;//cnt计算了重复的,当它>m时减去多的R
  30. res+=(LL)(a[i]+end)*c/2;
  31. }
  32. }
  33. cout<<res-(cnt-m)*r;
  34. }

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的上取整,事实上,我们可以取到任意的该长度的区间,如何证明?

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

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

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

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/374361
推荐阅读
相关标签
  

闽ICP备14008679号