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

树状数组

时间:2023-01-11 16:47:26浏览次数:44  
标签:le 树状 LL 数组 区间 sum

目录

树状数组基础

image

区间修改,单点查询:P3368 【模板】树状数组 2

题目描述

如题,已知一个数列,你需要进行下面两种操作:

  • 1 x y k:将区间 \([x, y]\) 内每个数加上 \(k\)。
  • 2 x:输出第 \(x\) 个数的和。

数据范围
对于 \(100\%\) 的数据:\(1 \leq N, M\le 500000\),\(1 \leq x, y \leq n\),保证任意时刻序列中任意元素的绝对值都不大于 \(2^{30}\)。

区间修改,区间查询:P3372 【模板】线段树 1

题目描述

如题,已知一个数列,你需要进行下面两种操作:

  • 1 x y k:将区间 \([x, y]\) 内每个数加上 \(k\)。
  • 2 x y:输出区间 \([x, y]\) 内每个数的和。

数据范围
对于 \(100\%\) 的数据:\(1 \le n, m \le {10}^5\)。
保证任意时刻数列中所有元素的绝对值之和 \(\le {10}^{18}\)。

分析
区间修改可以使用差分 \(D[i] = a[i]-a[i-1]\);
区间查询,使用区间和 \(sum(l,r)=sum(r)-sum(l-1)\);

差分的前缀和是元素组:\(a[i]=D[1]+D[2]+...+D[i]\)

\[\begin{aligned} &a[1]+a[2]+...+a[k] \\ &= D[1] + D[1]+D[2] + D[1]+D[2]+D[3] +...+ D[1]+D[2]+...+D[k]\\ &= kD[1] + (k-1)D[2] + (k-2)D[3] + ... + (k-(k-1))D[k] \\ &= k\sum_{i=1}^{k}D[i] - \sum_{i=1}^{k} {(i-1)D[i]} \end{aligned} \]

通过 2 个树状数组维护 \(D[i]\) 和 \((i-1)D[i]\)
复杂度 \(O(mlogn)\)

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e6+10;
LL n,q,a[N];
LL tr1[N], tr2[N];

#define lowbit(x)  (x&(-x))
void add(LL tr[],LL x,LL y) {
    while(x<=n) tr[x]+=y, x+=lowbit(x);
}
LL sum(LL tr[],LL x) {
    LL ans=0;
    while(x) ans+=tr[x], x-=lowbit(x);
    return ans;
}

int main() {
    scanf("%lld%lld", &n,&q);
    for(int i=1; i<=n; i++) scanf("%lld", &a[i]);
    for(int i=1; i<=n; i++) {
        add(tr1, i, a[i]-a[i-1]);
        add(tr2, i, (a[i]-a[i-1])*(i-1));
    }
    LL op,l,r,x;
    while(q--) {
        scanf("%lld%lld%lld", &op, &l, &r);
        if(op==1) {
            scanf("%lld", &x);
            add(tr1, l, x), add(tr1, r+1, -x);
            add(tr2, l, x*(l-1)), add(tr2, r+1, -x*(r+1-1));
        } else {
            LL ans=(r*sum(tr1,r)-sum(tr2,r)) - ((l-1)*sum(tr1,l-1)-sum(tr2,l-1));
            printf("%lld\n", ans);
        }
    }
    return 0;
}

标签:le,树状,LL,数组,区间,sum
From: https://www.cnblogs.com/hellohebin/p/17044187.html

相关文章

  • 数组中改变/不改变原始数组的方法
    不会改变原来数组【concat()、every()、some()、filter()、map()、slice()】concat()//concat()用于连接两个或多个字符串//该方法没有改变原有字符串,但是会返回连......
  • Spring 缓存 key 使用数组传参
    出错使用@Override@Cacheable(cacheNames="cacheName",key="T(java.lang.String).join(#envKey)")publicObjectjoin(String...envKey){r......
  • 数组添加元素
      cattest.sh#定义一个空的数组array=()ping-w1192.168.1.1>/dev/null2>&1array+=($?)ping-w1192.168.1.1>/dev/null2>&1array+=($?)ping-w......
  • 数组描述线性表(C++实现)
    线性表也称有序表,其每一个实例都是元素的一个有序集合抽象类linearList一个抽象类包含没有实现代码的成员函数,这样的成员函数称为纯虚函数,用数字0作为初始值来说明templ......
  • 【二分查找】LeetCode 34. 在排序数组中查找元素的第一个和最后一个位置
    题目链接34.在排序数组中查找元素的第一个和最后一个位置思路转自:林小鹿的题解两套二分查找模板,分别用来查找左边界和右边界intbsearch_1(intl,intr){whil......
  • 后缀数组 II —— height 数组及其求法
    上集:后缀数组I——后缀排序记\(S_i\)表示以\(i\)为起点的后缀,\(sa_i\)表示对\(s\)进行后缀排序后排名为\(i\)的后缀,\(SA_i\)表示对\(s\)进行后缀排序......
  • 找出整型数组中重复次数最多元素集合中的最小值
    考虑用map去处理,然后筛选出map里值最大的元素集合,最后集合中键最小的那个元素  importjava.util.*;importjava.util.stream.Collectors;publicclassMain{......
  • Day11:数组基础知识
    packagecom.dfyfhqsgclxry.array;publicclassArrayDemo08{publicstaticvoidmain(String[]args){//1.创建一个二维数组11*11,0:没有棋子1:黑棋2:白棋int[......
  • leetcode215-数组中的第K个最大元素
    思路我自己想到的是用排序,然后取下标为n-k的数字,但是这样时间复杂度是O(nlogn),不符合题目要求题解中的快速排序法很好,我也想到了快速排序,但是具体实现没有写出来要点......
  • solidity 内存(memory) 可变数组的增删改查 操作
    //SPDX-License-Identifier:MITpragmasolidity^0.8.9;libraryArray{functionpush(uint256[]memory_nums,uint256_num)internalpure{assemb......