树状数组-算法日常练习记录

树状数组可以通过下面这个网站进行学习:

树状数组 - OI Wiki (oi-wiki.org)

#130. 树状数组 1 :单点修改,区间查询

#130. 树状数组 1 :单点修改,区间查询 - 题目 - LibreOJ (loj.ac)

"""
https://loj.ac/p/130
单点修改,区间查询
"""


def lowbit(x: int):
    return x & -x


def getsum(x):
    ans = 0
    while x > 0:
        ans += c[x]
        x -= lowbit(x)
    return ans


def add(pivot, v):
    while pivot <= n:
        c[pivot] += v
        pivot += lowbit(pivot)


if __name__ == '__main__':
    n, q = map(int, input().strip().split(" "))
    lst = [-1] + list(map(int, input().strip().split(" ")))  # 方便下标操作
    ops = [(map(int, input().strip().split(" "))) for _ in range(q)]
    c = [0] * (n + 10)  # 建立
    res = []
    # 建树
    for i in range(1, n + 1):
        add(i, lst[i])
    del lst
    for op in ops:
        t, x, y = op
        if t == 1:
            add(x, y)
        else:
            res.append(getsum(y) - getsum(x - 1))
    for i in res:
        print(i)

#131. 树状数组 2 :区间修改,单点查询

#131. 树状数组 2 :区间修改,单点查询 - 题目 - LibreOJ (loj.ac)

"""
https://loj.ac/p/130
单点修改,区间查询
"""


def lowbit(x: int):
    return x & -x


def getsum(x):
    ans = 0
    while x > 0:
        ans += c[x]
        x -= lowbit(x)
    return ans


def add(pivot, v):
    while pivot <= n:
        c[pivot] += v
        pivot += lowbit(pivot)


if __name__ == '__main__':
    n, q = map(int, input().strip().split(" "))
    lst = [0] + list(map(int, input().strip().split(" ")))  # 方便下标操作
    ops = [list(map(int, input().strip().split(" "))) for _ in range(q)]
    c = [0] * (n + 10)  # 建立
    # O(n)版本,利用前缀和
    for i in range(1, n + 1):
        c[i] = lst[i] - lst[i - lowbit(i)]
    for i in range(n,0,-1):
        lst[i] = lst[i] - lst[i - 1]
    res = []
    # 建树
    # O(nlogn)版本
    # for i in range(1, n + 1):
    #     add(i, lst[i])
    for op in ops:
        type, t = op[0], op[1:]
        if type == 1:
            x, y, z = t
            add(x, z)
            add(y + 1, -z)
        else:
            t = t[0]
            print(getsum(t))

#132. 树状数组 3 :区间修改,区间查询

#132. 树状数组 3 :区间修改,区间查询 - 题目 - LibreOJ (loj.ac)

"""
https://loj.ac/p/132
区间加区间和
"""


def lowbit(x):
    return x & -x


def add(pivot, x, tr, n):
    while pivot <= n:
        tr[pivot] += x
        pivot += lowbit(pivot)


def getsum(pivot, tr):
    ans = 0
    while pivot > 0:
        ans += tr[pivot]
        pivot -= lowbit(pivot)
    return ans


def getAllSum(x, tr_d, tr_di):
    return getsum(x, tr_d) * (x + 1) - getsum(x, tr_di)


n, q = map(int, input().strip().split(" "))
lst = [0] + list(map(int, input().strip().split(" ")))
ops = [list(map(int, input().strip().split(" "))) for _ in range(q)]
tr_d = [0] * (n + 10)
tr_di = [0] * (n + 10)
# 构造差分数组
for i in range(n, 0, -1):
    lst[i] = lst[i] - lst[i - 1]
# 初始化tr_d & tr_di 时间复杂度O(nlogn)
for i in range(1, n + 1):
    add(i, lst[i], tr_d, n)
    add(i, lst[i] * i, tr_di, n)
# 开始操作
for op in ops:
    op_type, t = op[0], op[1:],
    if op_type == 1:
        l, r, x = t
        add(l, x, tr_d, n)
        add(r + 1, -x, tr_d, n)
        add(l, x * l, tr_di, n)
        add(r + 1, -x * (r + 1), tr_di, n)
    else:
        l, r = t
        res = getAllSum(r, tr_d, tr_di) - getAllSum(l - 1, tr_d, tr_di)
        print(res)

1265. 数星星

1265. 数星星 - AcWing题库

"""
https://www.acwing.com/problem/content/1267/
"""


def lowbit(x):
    return x & -x


def add(pivot, x, tr, n):
    while pivot <= n:
        tr[pivot] += x
        pivot += lowbit(pivot)


def getsum(pivot, tr):
    ans = 0
    while pivot:
        ans += tr[pivot]
        pivot -= lowbit(pivot)
    return ans


n = int(input())
lst = [list(map(int, input().split(" "))) for _ in range(n)]
N = 32010
tr = [0] * (N + 10)
res = []
ans = [0] * n
for x, y, in lst:
    add(x + 1, 1, tr, N)
    # 算出每一个星星的星级
    res.append(getsum(x + 1, tr) - 1)
# 整理答案
for r in res:
    ans[r] += 1
# 输出答案
for a in ans:
    print(a)

LCR 170. 交易逆序对的总数

LCR 170. 交易逆序对的总数 - 力扣(LeetCode)

"""
https://leetcode.cn/problems/shu-zu-zhong-de-ni-xu-dui-lcof/
求逆序对
"""


def re_lst(lst):
    """离散化数组"""
    tem = [(pivot, i) for pivot, i in enumerate(lst)]
    tem.sort(key=lambda x: x[1])
    for i in range(len(tem)):
        lst[i] = tem[i][0] + 1  # 从1开始,方便树状数组


def lowbit(x):
    return x & -x


def add(pivot, x, tr, n):
    while pivot <= n:
        tr[pivot] += x
        pivot += lowbit(pivot)


def getSum(pivot, tr):
    ans = 0
    while pivot:
        ans += tr[pivot]
        pivot -= lowbit(pivot)
    return ans


def getPairs(lst):
    """顺序对"""
    n = len(lst)
    tr = [0] * (n + 10)
    ans = 0
    for p, i in enumerate(lst):
        add(i, 1, tr, n)
        ans += getSum(i, tr) - 1
    return ans


def getReversePairs(lst: list):
    n = len(lst)
    tr = [0] * (n + 10)
    ans = 0
    for i in range(n - 1, -1, -1):
        add(lst[i], 1, tr, n)
        ans += getSum(lst[i], tr) - 1
    return ans


lst = [4, 3, 2, 1]
re_lst(lst)
print(lst)
# 先求顺序对
t = getPairs(lst)
print(t)
# 求逆序对
print(getReversePairs(lst))

1215. 小朋友排队

1215. 小朋友排队 - AcWing题库

"""
https://www.acwing.com/problem/content/1217/
使用树状数组解决该问题
"""


def re_lst(lst):
    """离散化数组"""
    tem = [(pivot, i) for pivot, i in enumerate(lst)]
    tem.sort(key=lambda x: x[1])
    for i in range(len(tem)):
        lst[i] = tem[i][0] + 1  # 从1开始,方便树状数组


def lowbit(x):
    return x & -x


def add(pivot, x, tr, n):
    while pivot <= n:
        tr[pivot] += x
        pivot += lowbit(pivot)


def getSum(pivot, tr):
    ans = 0
    while pivot:
        ans += tr[pivot]
        pivot -= lowbit(pivot)
    return ans


def getPairs(lst):
    """顺序对"""
    n = len(lst)
    tr = [0] * (n + 10)
    for p, i in enumerate(lst):
        add(i, 1, tr, n)
        num[i] += getSum(n,tr) - getSum(i, tr) # 关键步骤
    return


def getReversePairs(lst: list):
    n = len(lst)
    tr = [0] * (n + 10)
    for i in range(n - 1, -1, -1):
        add(lst[i], 1, tr, n)
        num[lst[i]] += getSum(lst[i], tr) - 1 # 关键步骤
    return


n = int(input())
lst = list(map(int, input().strip().split(" ")))
re_lst(lst)
num = [0] * (n + 10)  # 记录交换次数的数组
# 计算逆序
getReversePairs(lst)
# 同上
getPairs(lst)
# 计算结果
res = 0
for v in num:
    res += ((1 + v) * v) // 2
print(res)

  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
算法与数据结构它们分别涵盖了以下主要内容: 数据结构(Data Structures): 逻辑结构:描述数据元素之间的逻辑关系,如线性结构(如数组、链表)、树形结构(如二叉树、堆、B树)、图结构(有向图、无向图等)以及集合和队列等抽象数据类型。 存储结构(物理结构):描述数据在计算机中如何具体存储。例如,数组的连续存储,链表的动态分配节点,树和图的邻接矩阵或邻接表表示等。 基本操作:针对每种数据结构,定义了一系列基本的操作,包括但不限于插入、删除、查找、更新、遍历等,并分析这些操作的时间复杂度和空间复杂度。 算法算法设计:研究如何将解决问题的步骤形式化为一系列指令,使得计算机可以执行以求解问题。 算法特性:包括输入、输出、有穷性、确定性和可行性。即一个有效的算法必须能在有限步骤内结束,并且对于给定的输入产生唯一的确定输出。 算法分类:排序算法(如冒泡排序、快速排序、归并排序),查找算法(如顺序查找、二分查找、哈希查找),图论算法(如Dijkstra最短路径算法、Floyd-Warshall算法、Prim最小生成树算法),动态规划,贪心算法,回溯法,分支限界法等。 算法分析:通过数学方法分析算法的时间复杂度(运行时间随数据规模增长的速度)和空间复杂度(所需内存大小)来评估其效率。 学习算法与数据结构不仅有助于理解程序的内部工作原理,更能帮助开发人员编写出高效、稳定和易于维护的软件系统。
算法与数据结构它们分别涵盖了以下主要内容: 数据结构(Data Structures): 逻辑结构:描述数据元素之间的逻辑关系,如线性结构(如数组、链表)、树形结构(如二叉树、堆、B树)、图结构(有向图、无向图等)以及集合和队列等抽象数据类型。 存储结构(物理结构):描述数据在计算机中如何具体存储。例如,数组的连续存储,链表的动态分配节点,树和图的邻接矩阵或邻接表表示等。 基本操作:针对每种数据结构,定义了一系列基本的操作,包括但不限于插入、删除、查找、更新、遍历等,并分析这些操作的时间复杂度和空间复杂度。 算法算法设计:研究如何将解决问题的步骤形式化为一系列指令,使得计算机可以执行以求解问题。 算法特性:包括输入、输出、有穷性、确定性和可行性。即一个有效的算法必须能在有限步骤内结束,并且对于给定的输入产生唯一的确定输出。 算法分类:排序算法(如冒泡排序、快速排序、归并排序),查找算法(如顺序查找、二分查找、哈希查找),图论算法(如Dijkstra最短路径算法、Floyd-Warshall算法、Prim最小生成树算法),动态规划,贪心算法,回溯法,分支限界法等。 算法分析:通过数学方法分析算法的时间复杂度(运行时间随数据规模增长的速度)和空间复杂度(所需内存大小)来评估其效率。 学习算法与数据结构不仅有助于理解程序的内部工作原理,更能帮助开发人员编写出高效、稳定和易于维护的软件系统。
逻辑结构:描述数据元素之间的逻辑关系,如线性结构(如数组、链表)、树形结构(如二叉树、堆、B树)、图结构(有向图、无向图等)以及集合和队列等抽象数据类型。 存储结构(物理结构):描述数据在计算机中如何具体存储。例如,数组的连续存储,链表的动态分配节点,树和图的邻接矩阵或邻接表表示等。 基本操作:针对每种数据结构,定义了一系列基本的操作,包括但不限于插入、删除、查找、更新、遍历等,并分析这些操作的时间复杂度和空间复杂度。 算法算法设计:研究如何将解决问题的步骤形式化为一系列指令,使得计算机可以执行以求解问题。 算法特性:包括输入、输出、有穷性、确定性和可行性。即一个有效的算法必须能在有限步骤内结束,并且对于给定的输入产生唯一的确定输出。 算法分类:排序算法(如冒泡排序、快速排序、归并排序),查找算法(如顺序查找、二分查找、哈希查找),图论算法(如Dijkstra最短路径算法、Floyd-Warshall算法、Prim最小生成树算法),动态规划,贪心算法,回溯法,分支限界法等。 算法分析:通过数学方法分析算法的时间复杂度(运行时间随数据规模增长的速度)和空间复杂度(所需内存大小)来评估其效率。 学习算法与数据结构不仅有助于理解程序的内部工作原理,更能帮助开发人员编写出高效、稳定和易于维护的软件系统。
逻辑结构:描述数据元素之间的逻辑关系,如线性结构(如数组、链表)、树形结构(如二叉树、堆、B树)、图结构(有向图、无向图等)以及集合和队列等抽象数据类型。 存储结构(物理结构):描述数据在计算机中如何具体存储。例如,数组的连续存储,链表的动态分配节点,树和图的邻接矩阵或邻接表表示等。 基本操作:针对每种数据结构,定义了一系列基本的操作,包括但不限于插入、删除、查找、更新、遍历等,并分析这些操作的时间复杂度和空间复杂度。 算法算法设计:研究如何将解决问题的步骤形式化为一系列指令,使得计算机可以执行以求解问题。 算法特性:包括输入、输出、有穷性、确定性和可行性。即一个有效的算法必须能在有限步骤内结束,并且对于给定的输入产生唯一的确定输出。 算法分类:排序算法(如冒泡排序、快速排序、归并排序),查找算法(如顺序查找、二分查找、哈希查找),图论算法(如Dijkstra最短路径算法、Floyd-Warshall算法、Prim最小生成树算法),动态规划,贪心算法,回溯法,分支限界法等。 算法分析:通过数学方法分析算法的时间复杂度(运行时间随数据规模增长的速度)和空间复杂度(所需内存大小)来评估其效率。 学习算法与数据结构不仅有助于理解程序的内部工作原理,更能帮助开发人员编写出高效、稳定和易于维护的软件系统。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值