首页 > 其他分享 >树状数组

树状数组

时间:2023-07-11 22:46:24浏览次数:48  
标签:return 树状 int 数组 logn data

概念

https://zhuanlan.zhihu.com/p/92920381

树状数组(Binary Indexed Tree, 又Fenwick Tree)其实并不是一棵树,只是对数组各元素进行逻辑上的划分。根据维基百科,树状数组是一种用于高效计算数列前缀和的数据结构,它可以以O(logn)的时间得到任意前缀和(两个前缀和相减即可得到区间和),并同时支持以O(logn)的时间对数组某个值进行修改,空间复杂度为O(n)。由此可见,我们可以用树状数组解此题,使sumRangeupdate的复杂度均为O(logn)。因此我们有必要来了解一下树状数组。

 

视频帮助理解

https://www.bilibili.com/video/BV1ce411u7qP/?spm_id_from=333.337.search-card.all.click&vd_source=41b9bfb5ef0a4175a4cb4170a475f680

 

题目

https://www.luogu.com.cn/problem/P3374

 

Code

#include <bits/stdc++.h>
#include <unistd.h>
using namespace std;

int v[500005], bit[500005], data[500005];

int n, m;

int lowBit(int j){
    return j & (-j);
}

int sum(int i){ // 前idx个数的和, logn
    // 这里的i从1开始编号
    int res = 0;
    while(i > 0){
        res += bit[i];
        i -= lowBit(i);
    }
    return res;
}

int sumRange(int i, int j) { //logn
    return sum(j) - sum(i-1);
}

void update(int i, int val) { //logn
    int diff = val - data[i];
    data[i] = val;
    // bit中下标从1开始
    while(i <= n){
        bit[i] += diff;
        i += lowBit(i);
    }
}

void print(){
    for(int i=1; i<=n; i++){
        cout << bit[i] << ",";
    }

    cout << endl;
}

int main() {
    cin >> n >> m;
    
    for(int i=1; i<=n; i++){
        cin >> v[i];
    }

    for(int i=1; i<=n; i++){
        update(i, v[i]);
        
//        cout << "-------------" << endl;
//        cout << "update i=" << i << " with v[i]=" << v[i] << endl;
//        
//        print();
    }

    for(int i=0; i<m; i++){
        int action, x;
        cin >> action >> x;
        
        if (action == 1){
            // add k to x pos
            int k;
            cin >> k;
            
            update(x, k+data[x]);
            
//            cout <<"----- add k=" << k << " to x=" << x << endl;
//            print();
            
        } else if (action == 2){
            // query sum in the range of [x, y]
            int y;
            cin >> y;
            
            cout << sumRange(x, y) << endl;
        }
    }
}

 

标签:return,树状,int,数组,logn,data
From: https://www.cnblogs.com/lightsong/p/17546143.html

相关文章

  • HJ80 整型数组合并
    1.题目读题HJ80 整型数组合并  考查点 2.解法思路 代码逻辑 具体实现 publicclassHJ080{publicstaticvoidmain(String[]args){Scannersc=newScanner(System.in);intn1=sc.nextInt();int[]arr1=newint[n1]......
  • 「学习笔记」后缀数组
    感谢LB学长的博文!前置知识后缀是指从某个位置\(i\)开始到整个串末尾结束的一个特殊子串,也就是\(S[i\dots|S|-1]\)。计数排序-OIWiki(oi-wiki.org)基数排序-OIWiki(oi-wiki.org)变量后缀数组最主要的两个数组是sa和rk。sa表示将所有后缀排序后第\(i\)小......
  • 「模板」树状数组
    引入题目描述给定\(n\)个数\(a[1],a[2],a[3]...a[n]\),现在又下面两种操作:1.询问区间\([x,y]\)的和,并输出。2.将下标为\(x\)的数增加\(val\)。一共\(x\)此操作\(1\len,m\le100000\),保证在\(int\)范围内。方法一:暴力枚举定义数组\(a\)储存\(n\)个元素。求区间和的时间复......
  • 动态数组和C++ std::vector详解
    目录1.std::vector2.vector的用法    2.1vector的定义和声明    2.2成员函数        2.2.1基本函数            operator=            assign            get_allocator        2.2.2元素访问   ......
  • 代码随想录算法训练营第二十九天| 1005.K次取反后最大化的数组和 134. 加油站 135. 分
      860.柠檬水找零 思路:遇到20,先给10和5,再给三个5代码:1boollemonadeChange(vector<int>&bills){2if(bills.size()==0)returntrue;34map<int,int>currentMoney;5for(inti=0;i<bills.size();i++)6{7if......
  • vue3中父组件与组件之间参数传递,使用(defineProps/defineEmits),涉及属性传递,对象传递,
    Vue3中子父组件之间的通信一、父组件传递参数到子组件采用defineProps传递属性父组件:<template><div><h1>这是父组件</h1><h1>父组件像子组件传递参数</h1><h2>传递属性值</h2><HH:fatherMessage="fatherMessage":valNum="valNum":valBool=......
  • 挑战程序竞赛系列(70):4.7后缀数组(2)
    挑战程序竞赛系列(70):4.7后缀数组(2)传送门:POJ1509:GlassBeads题意:ThedescriptionofthenecklaceisastringA=a1a2…amspecifyingsizesoftheparticularbeads,wherethelastcharacteramisconsideredtoprecedecharactera1incircularfashion.Thedisjoin......
  • LeetCode 215. 数组中的第K个最大元素
    小根堆classSolution{public:intfindKthLargest(vector<int>&nums,intk){priority_queue<int,vector<int>,greater<int>>q;for(autox:nums){if(q.size()<k)q.push(x);......
  • python练手项目——给数组中的每个字段加上双引号
    前言工作中经常会遇到一种场景:复制值时,会复制出来几个甚至十几个字段。把这些字段放入SQL语句或者接口里面时,需要手动给每个字段加上引号,很浪费时间。因此我想要写一个python脚本,给字段自动加上引号。测试数据1:上海武汉广州深圳北京内蒙古呼和浩特2:张三,李四,王五,......
  • #yyds干货盘点# LeetCode程序员面试金典:区域和检索 - 数组不可变
    1.简述:给定一个整数数组 nums,处理以下类型的多个查询:计算索引 left 和 right (包含left和right)之间的nums元素的和,其中 left<=right实现NumArray类:NumArray(int[]nums)使用数组nums初始化对象intsumRange(inti,intj)返回数组nums 中索引 left 和 r......