当前位置: 首页 > news >正文

“二分查找 + (必要时)前缀和” -- 处理 ’有序数组‘ 的区间问题汇总

例题1:
P3184 [USACO16DEC] Counting Haybales S - 洛谷

import sys, bisect

# def satisfied(hay):
#     return True if hay in hays else False
    

data = sys.stdin.read().split()
data = iter(data)

ans = []
N = int(next(data))
Q = int(next(data))

hays = [int(next(data)) for _ in range(N)]
hays.sort() # 2 3 5 7 这样看区间比较直观

for _ in range(Q):
    start = int(next(data))
    end = int(next(data))
    
    # .index() 太慢 -- 线性查找,不适合大数据  --> 建议bisect用于查找第一个target的位置
    # interval = hays.index(end) - hays.index(start) + 1 # index从0开始,需补1
    s_index = bisect.bisect_left(hays, start)
    e_index = bisect.bisect_right(hays, end)
    interval = e_index - s_index # # index从0开始,需补1
    
    ans.append(interval)

sys.stdout.write("\n".join(map(str, ans)))

题目1:区间和查询(Range Sum Query)

题目描述
给定一个已排序的非负整数数组(长度 n),以及 Q 个查询。每个查询给出两个整数 L 和 R(表示数值),要求输出数组中所有落在 [L,R] 内的数的和;如果没有则输出 0。

import sys
import bisect
from itertools import accumulate

def range_sum_query():
    data = sys.stdin.read().split()
    it = iter(data)
    n = int(next(it))
    q = int(next(it))
    # 读取数组(题目保证数组已排序,否则需要 sort)
    arr = [int(next(it)) for _ in range(n)]
    # 构造前缀和:prefix[i] 表示前 i 个元素的和(prefix[0]=0)
    prefix = [0] + list(accumulate(arr))
    
    out_lines = []
    for _ in range(q):
        L = int(next(it))
        R = int(next(it))
        # 左边界:第一个不小于 L 的位置
        left = bisect.bisect_left(arr, L)
        # 右边界:第一个大于 R 的位置
        right = bisect.bisect_right(arr, R)
        sum_val = prefix[right] - prefix[left]
        out_lines.append(str(sum_val))
    
    sys.stdout.write("\n".join(out_lines))

if __name__ == '__main__':
    range_sum_query()

题目2:大于某值的元素计数

题目描述
给定一个升序排列的数组和 Q个查询。每个查询给定一个整数 X,要求输出数组中大于 X 的元素个数

 

import sys, bisect

def count_greater():
    data = sys.stdin.read().split()
    it = iter(data)
    n = int(next(it))
    q = int(next(it))
    arr = [int(next(it)) for _ in range(n)]
    # 确保数组升序
    arr.sort()
    
    out_lines = []
    for _ in range(q):
        X = int(next(it))
        pos = bisect.bisect_right(arr, X)
        count = n - pos
        out_lines.append(str(count))
    
    sys.stdout.write("\n".join(out_lines))

if __name__ == '__main__':
    count_greater()

题目3:指定区间内的平均值查询

题目描述
给定一个排序好的数组和 Q 个查询,每个查询给出两个整数 L 和 R,要求计算数组中落在 [L,R] 内所有数的平均值;如果该区间内没有数字,则输出 -1

import sys, bisect
from itertools import accumulate

def interval_average_query():
    data = sys.stdin.read().split()
    it = iter(data)
    n = int(next(it))
    q = int(next(it))
    arr = [int(next(it)) for _ in range(n)]
    # 确保数组升序
    arr.sort()
    prefix = [0] + list(accumulate(arr))
    
    out_lines = []
    for _ in range(q):
        L = int(next(it))
        R = int(next(it))
        left = bisect.bisect_left(arr, L)
        right = bisect.bisect_right(arr, R)
        count = right - left
        if count == 0:
            out_lines.append("-1")
        else:
            sum_val = prefix[right] - prefix[left]
            avg = sum_val / count
            out_lines.append(str(avg))
    
    sys.stdout.write("\n".join(out_lines))

if __name__ == '__main__':
    interval_average_query()

题目4:“近似”区间计数问题

题目描述
给定一个升序排列的数组和 Q 个查询。每个查询给定两个整数 XX和 K,要求统计数组中所有与 X 的差值不超过 K 的元素个数,即统计区间 [X−K,X+K] 内的元素个数

import sys, bisect

def approximate_interval_count():
    data = sys.stdin.read().split()
    it = iter(data)
    n = int(next(it))
    q = int(next(it))
    arr = [int(next(it)) for _ in range(n)]
    arr.sort()
    
    out_lines = []
    for _ in range(q):
        X = int(next(it))
        K = int(next(it))
        L = X - K
        R = X + K
        left = bisect.bisect_left(arr, L)
        right = bisect.bisect_right(arr, R)
        count = right - left
        out_lines.append(str(count))
    
    sys.stdout.write("\n".join(out_lines))

if __name__ == '__main__':
    approximate_interval_count()

题目5:区间频率统计

题目描述
给定一个升序排列的数组和 Q 个查询,每个查询给定一个目标值 X,要求输出 X 在数组中出现的次数

import sys, bisect

def frequency_count():
    data = sys.stdin.read().split()
    it = iter(data)
    n = int(next(it))
    q = int(next(it))
    arr = [int(next(it)) for _ in range(n)]
    arr.sort()
    
    out_lines = []
    for _ in range(q):
        X = int(next(it))
        left = bisect.bisect_left(arr, X)
        right = bisect.bisect_right(arr, X)
        count = right - left
        out_lines.append(str(count))
    
    sys.stdout.write("\n".join(out_lines))

if __name__ == '__main__':
    frequency_count()

http://www.dtcms.com/a/109917.html

相关文章:

  • 信息学奥赛一本通 1524:旅游航道
  • 胶铁一体化产品介绍
  • 什么是 SAML身份验证
  • 【DY】信息化集成化信号采集与处理系统;生物信号采集处理系统一体机
  • Qt实现登录界面(输入密码后过几秒,密码变为小黑点,眼睛改变密码明文,密文)
  • 电子电气架构 --- SOC设计流程及其集成开发环境
  • 企业知识库如何搭建?从零开始构建高效知识管理体系
  • 【Spring】Spring 注解解码:@RequestBody 与 @ResponseBody 的双向桥梁艺术
  • 2024年B会(Coling)——双重对比学习用于多模态对话情感识别
  • 数字人训练数据修正和查看 不需要GPU也能运行的DH_live-加载自己训练-
  • 注意力机制在大语言模型中的原理与实现总结
  • 【算法中的数学】分解质因数
  • 每天学一个 Linux 命令(11):cp
  • 【系统移植】(六)第三方驱动移植
  • MySQL:数据类型
  • 380_C++_[结合379]从连续内存地址中取出来的热力图图片data,转换为可视化的、带颜色的热力图像显示到界面(图像格式为RGBA)
  • Yapi部署指南:在 Linux 上 Yapi 教程
  • Linux Bash 脚本实战:自动监控域名证书过期并发送邮件告警
  • vue和angular实现飞机大战
  • 彩虹表攻击
  • 52.个人健康管理系统小程序(基于springbootvue)
  • Linux 高级命令与常见操作:文本处理、系统管理与网络调试
  • 红米AC2100-刷OpenWrt系统,安装zerotier教程
  • 7-6 混合类型数据格式化输入
  • 大数据(4)Hive数仓三大核心特性解剖:面向主题性、集成性、非易失性如何重塑企业数据价值?
  • PPT助手:一款集计时、远程控制与多屏切换于一身的PPT辅助工具
  • 【备忘】在Docker中安装宝塔面板,实现环境隔离,又能快速迁移服务器环境
  • 基于Flask的MBA考生成绩查询系统设计与实现
  • Java 可变参数(Varargs)使用指南
  • Vue实例中,setTimeout()不生效怎么解决