首页 > 其他分享 >P3374 【模板】树状数组 动态求连续区间和 刷题笔记

P3374 【模板】树状数组 动态求连续区间和 刷题笔记

时间:2024-03-16 15:31:38浏览次数:21  
标签:return 树状 int lowbit 修改 res P3374 include 刷题

我们创建如下的树状数组来辅助操作

该数组每个s[i]处于第几层取决于其二进制 最后低位 的1处于从右往左数第几列

显然所有奇数的最右边一位都是1 即其最低位的1 处于右边第一列

所以所有的奇数处于第一层

而2,6,10,14的最低位1处于右边第二列  所以这些数处于第二层 

8 的最低位1处于右数第三列 所以8处于第三列

以此类推 

该结构的好处在于  如果我们只修改单个元素 的值

只需要 logn 的次数就可以完成对单元素及其区间和的修改

例如 对3进行修改 

只需要三次操作 即可修改该元素  并且完成s[4] ,s[8],s[16]的前缀和的修改

而一般前缀和则需要修改 16次

至于想查看a[1-7]的和怎么办 此时只修改了s[4]并没有修改s[7]

这个疑问等会看我们的查询函数即可

先看修改的实现

我们在修改的时候往上一层 层层修改即可

使用 lowbit 函数返回查询数的最后一位1的大小

int lowbit(int x){

    return x&-x;
}

修改函数 

void change (int x,int k){
    while(x<=n){
        s[x]+=k;//上述例子的s[4],s[8],s[16]
        x+=lowbit(x);//依据层次不同 1 的最低位不同更换x的位置
        
    }
}

查询函数

我们想查询a[1]+a[2]+...+a[7]

如图只需s[7]+s[6]+s[4]即可

并且我们上面提到  虽然我们只修改了s[3],s[4]

但是我们此时算区间和的时候 加上了s[4]

所以仍然完成了对a[1]+a[2]+...+a[7]的区间和的修改

int query(int x){
    int res=0;
    while(x){
        res+=s[x];
        x-=lowbit(x);//根据我们建立层数的特性改变X
    }
    return res;    
}

完整代码

#include<iostream>

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<sstream>
using namespace std;
const int N=1e8+10;
int n,m;
int a[N],s[N];
int lowbit(int x){

    return x&-x;
}

void change (int x,int k){
    while(x<=n){
        s[x]+=k;
        x+=lowbit(x);
        
    }
}
int query(int x){
    int res=0;
    while(x){
        res+=s[x];
        x-=lowbit(x);
    }
    return res;    
}
int main(){
    /*for(int i=2;i<=16;i+=2){
        cout<<i<<"的二进制最后一位为"<<lowbit(i)<<endl;
    }*/ 
    
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    for(int i=1;i<=n;i++){
        change(i,a[i]);
    }
    while(m--){
        int x,y,z;
        cin>>x>>y>>z;
        if(x==1){
            change(y,z);
        }else{
            cout<<query(z)-query(y-1)<<endl;
        }
    }
    
    return 0;
}

标签:return,树状,int,lowbit,修改,res,P3374,include,刷题
From: https://blog.csdn.net/2301_78763076/article/details/136762317

相关文章

  • 日期问题 刷题笔记
    思路枚举19600101到20591231这个区间的数获得年月日 判断是否合法如果合法 关于题目给出的日期有三种可能年/月/日日/月/年月/日/年判断是否和题目给出的日期符合如果符合输出闰年{1.被4整除不被100整除  2.被400整除}补位写法“%02d" 如果不足两位......
  • Leetcode刷题-动态规划-最长回文子串
    链接:5.最长回文子串-力扣(LeetCode)给你一个字符串s,找到s中最长的回文子串,如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。示例1:输入:s="babad"输出:"bab"解释:"aba"同样是符合题意的答案。示例2:输入:s="cbbd"输出:"bb"提示:1<=s.length<=1000s......
  • 树状数组
    模板题:https://www.luogu.com.cn/problem/P3374题解:#include<bits/stdc++.h>usingnamespacestd;constintN=5e5+5;intm,n;intc[N];intlowbit(intx){ returnx&-x;}intquery(intx){ intres=0; while(x){ res+=c[x]; x=x......
  • 力扣刷题Days19-637.二叉树的层平均数
    目录1,题目2,代码2.1广度优先遍历2.2深度优先遍历3,学习与总结1,题目给定一个非空二叉树的根节点 root ,以数组的形式返回每一层节点的平均值。2,代码2.1广度优先遍历/***Definitionforabinarytreenode.*functionTreeNode(val,left,right){*......
  • 力扣刷题Days16 - 191.位1的个数(js)
    目录1,题目2,代码2.1逐位判断核心代码2.1.2逐位判断22.2位运算优化3,学习与总结1,题目编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为'1'的个数(也被称为汉明重量)。2,代码2.1逐位判断/***@param{number}n-apositivein......
  • 第一课——树状数组
    前缀和算法可以计算某一个区间的累记和,但是出现修改的时候,前缀和的效率便得不到保障。于是数状数组出现了。出现原因总结——需求从单纯的区间查询变为了单点修改+区间查询。树状数组本文不探讨树状数组的开发过程,这里先给出树状数组的结构:树状数组的设计非常巧妙,它让下标为......
  • 蓝桥杯刷题(七)
    [蓝桥杯2023省A]平方差题目描述输入格式输出格式样例#1样例输入#1样例输出#1提示【样例说明】【评测用例规模与约定】代码题目描述输入格式输出格式样例#1样例输入#1样例输出#1样例#2样例输入#2样例输出#2提示代码题目描述输入格式输出格式样例#1样......
  • 树状数组
    树状数组简介树状数组维护信息的类型:树状数组一般用来维护可差分的信息比如:累加和、累加乘或者出题人出了某个可差分的信息不可差分的信息:比如最大值、最小值不可差分的信息一般不用树状数组来维护,而会选择线段树来维护,因为线段树维护的思考难度低大多数情况下,线段树可以......
  • 2024最新华为OD机试,题库清单(按算法分类),高效刷题,举一反三,玩转OD
    目录专栏导读华为OD机试算法题太多了,知识点繁杂,如何刷题更有效率呢?一、逻辑分析二、数据结构1、线性表①数组②双指针2、map与list3、优先队列4、滑动窗口5、二叉树6、并查集7、栈三、算法1、基础算法①贪心算法②二分查找③分治递归④搜索算法⑤排序算法2、......
  • 深度优先搜索在树状数据结构中的应用
    深度优先搜索(DFS)是一种经典的树和图的遍历算法。它通过一条路径尽可能深地搜索树的分支,当节点v的所在边已经被探寻过,搜索将回溯到发现节点v的那条边的起始节点。这一过程一直进行到已发现从源节点可达的所有节点为止。以下是使用DFS在树状数据结构中搜索包含特定关键字的节点的一......