当前位置:   article > 正文

蓝桥杯(二)——二分与前缀和

蓝桥杯(二)——二分与前缀和

目录

一、二分

二、二分例题

1. 数的范围

2. 分巧克力

三、前缀和

四、前缀和例题

1. 子矩阵的和


一、二分

1. 方法一

1. 确定一个区间,使得目标值在一定区间中

2. 找一个性质满足:性质具有二段性;答案是二段性的分界点 

整数二分:

第一类:ans是红色区间的右端点(ans>=x)

将[L,R]分为[L,M-1]和[M,R]

ps:区间不是[L,M]的原因:M正好为红色时无法区分是在[L,M]还是[M+1,R]

if M是红色的,说明ans在区间[M,R]

else 说明ans在区间[L,M-1]

伪代码如下:注意算M时要+1,防止向下取整时发生死循环

  1. while l<r:
  2. m = l + r + 1 >> 1 # 等同(l+r+1)//2
  3. if m红:
  4. l = m # l=m时,需要+1
  5. else:
  6. r = m - 1

第二类:ans是绿色区间的左端点(ans<=x)

将[L,R]分为[L,M]和[M+1,R]

if M是绿色的,说明ans在区间[L,M]

else 说明ans在区间[M+1,R]

伪代码如下:

  1. while l<r:
  2. m = l + r >> 1 # 等同(l+r)//2
  3. if m绿:
  4. r = m # l=m时,不需要+1
  5. else:
  6. l = m + 1

2. 方法二  

思路:

1. 更据题目最后要求的量划分二分区域找到隔板

2. 套模板,思考isBlue函数应该怎么写,也就是什么是时候选择区间的左半部分。l和r的初始值需要比整个区间小1和大1。

3. 最后的值是l还是r

代码模板,每次根据题意改变isBlue函数:

  1. def isBlue(n):
  2. if n<target:
  3. return True
  4. else:
  5. return False
  6. nums = [5,7,7,8,8,10]
  7. target = 8
  8. l=-1
  9. r=len(nums)
  10. while l+1!=r:
  11. mid=l+r>>1
  12. if isBlue(nums[mid]):
  13. l=mid
  14. else:
  15. r=mid
  16. print(l,r)

二、二分例题

1. 数的范围

  1. n,q=map(int,input().split())
  2. s=list(map(int,input().split()))
  3. for i in range(q):
  4. find=int(input())
  5. #左边界
  6. l=0
  7. r=n-1
  8. while l<r:
  9. mid= l+r>>1 #等同(l+r)//2
  10. if s[mid]>=find:
  11. r=mid #r=mid时,不需要要+1
  12. else:
  13. l=mid+1
  14. if s[l]==find: #注意是l不是mid
  15. print(l,end=" ")
  16. else:
  17. print(-1,end=" ")
  18. #右边界
  19. l = 0
  20. r = n - 1
  21. while l < r:
  22. mid = l + r + 1 >> 1
  23. if s[mid] <= find:
  24. l = mid
  25. else:
  26. r = mid - 1
  27. if s[l] == find:
  28. print(l)
  29. else:
  30. print(-1)

2. 分巧克力

要点:

1.每块巧克力分的时候不可以拼接
2.每个人分得的巧克力大小相同
3.二分方法:以需要分的数量k作为临界点,当分的大小<=最大值时,sum(分得的巧克力数量)>=k

  1. n,k=map(int,input().split())
  2. h=[]
  3. w=[]
  4. for i in range(n):
  5. a,b=map(int,input().split())
  6. h.append(a)
  7. w.append(b)
  8. def check(m):
  9. sum=0
  10. for i in range(n):
  11. sum+=(h[i]//m)*(w[i]//m)#计算分的巧克力的总量
  12. if sum>=k:
  13. return True
  14. else:
  15. return False
  16. #以需要分的数量k作为临界点,当分的大小<=最大值时,sum(分得的巧克力数量)>=k
  17. l=1
  18. r=100000
  19. while l<r:
  20. m=l+r+1>>1
  21. if check(m):
  22. l=m
  23. else:
  24. r=m-1
  25. print(l)

三、前缀和

利用数列的前n项和来求下标从L,R和的值

四、前缀和例题

1. 子矩阵的和

思路:

1. 如何计算前缀和矩阵


2. 如何计算询问的结果

  1. n, m, q = map(int, input().split())
  2. grid=[[0 for i in range(m+1)]for j in range(n+1)]
  3. sum_grid=[[0 for i in range(m+1)]for j in range(n+1)] #前缀和矩阵
  4. #输入
  5. for i in range(n):
  6. a=list(map(int,input().split()))
  7. for j in range(m):
  8. grid[i+1][j+1]=a[j]
  9. #计算前缀和
  10. for i in range(1,n+1):
  11. for j in range(1,m+1):
  12. sum_grid[i][j]=sum_grid[i][j-1]+sum_grid[i-1][j]+grid[i][j]-sum_grid[i-1][j-1]
  13. result=[]
  14. #输出查询结果
  15. for i in range(q):
  16. x1,y1,x2,y2=map(int, input().split())
  17. sum=sum_grid[x2][y2]-sum_grid[x2][y1-1]-sum_grid[x1-1][y2]+sum_grid[x1-1][y1-1]
  18. result.append(sum)
  19. for i in result:
  20. print(i)

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

闽ICP备14008679号