P3368【模板】树状数组 2 - 差分

建立两个差分数组,套公式就好了
c[i]表示i元素的“增量”,下面的式子左边是序列从1 ~ x的前缀和整体增加的值
\[\sum_{i=1}^x\sum_{j=1}^ic[j] = (x+1)\sum_{i=1}^xc[i] - \sum_{i=1}^xi*c[i] \]

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
#define debug(x) cerr << #x << "=" << x << endl;
const int MAXN = 500000 + 10;
int n,m,tr[MAXN],c1[MAXN],c2[MAXN],sum[MAXN];
void update(int k, int p, int c[]) {
    while(p <= n) {
        c[p] += k;
        p += p&(-p);
    }
}
int getsum(int p, int c[]) {
    int sum = 0;
    while(p) {
        sum += c[p];
        p -= p&(-p);
    }
    return sum;
}
int main() {
    scanf("%d%d", &n, &m);
    for(int i=1; i<=n; i++) {
        int ai = 0;
        scanf("%d", &ai);
        sum[i] = sum[i-1] + ai;
    }
    for(int i=1; i<=m; i++) {
        int cmd, x, y, k;
        scanf("%d", &cmd);
        if(cmd == 1) {
            scanf("%d%d%d", &x, &y, &k);
            update(k, x, c1), update(-k, y+1, c1);
            update(k*x, x, c2), update(-k * (y+1), y+1, c2);
        } else {
            scanf("%d", &x);
            int ls = sum[x-1] + x * getsum(x-1, c1) - getsum(x-1, c2);
            int rs = sum[x] + (x+1) * getsum(x, c1) - getsum(x, c2);
            printf("%d\n", rs - ls);
        }
    }
    return 0;
} 

原文地址:https://www.cnblogs.com/Zolrk/p/9785343.html

时间: 2024-10-10 07:07:03

P3368【模板】树状数组 2 - 差分的相关文章

树状数组与差分

目录 树状数组的引入 lowbit的含义 树状数组的前缀和存储方式 单点修改 区间查询 初始化 模板例题--树状数组基本操作 差分--区间修改 备注 @(树状数组算法详解·目录) 树状数组的引入 相信读者一定知道什么是前缀和,形如一串数\(a1,a2...,an,sum[i]=a[1]+a[2]+...+a[i]\) 前缀和在算法的优化上占有很重要的地位,一般就会预先对数据进行预处理运算以后,再在运算过程中用\(O(1)\)时间调用,这样的操作很大程度上避免了实际运算中的枚举,NOIP2016魔

POJ3468 A Simple Problem with Interger [树状数组,差分]

题目传送门 A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 130735   Accepted: 40585 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One

Luogu3527 POI2011 Meteors 整体二分、树状数组、差分

传送门 比较板子的整体二分题目,时限有点紧注意常数 整体二分的过程中将时间在\([l,mid]\)之间的流星使用树状数组+差分进行维护,然后对所有国家查看一遍并分好类,递归下去,记得消除答案在\([mid+1,r]\)的询问中时间在\([l,mid]\)的流星操作的贡献 注意:可能存在某一段时间某一个国家的流星数量超过long long范围,应该当某个时候国家流星量和大于等于国家需求值时直接退出,这样可以避免这个问题. #include<bits/stdc++.h> #define INF 0

[模板]树状数组1/ZKW线段树

https://www.luogu.org/problemnew/show/P3374 1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 #define rson (o<<1|1) 5 #define lson (o<<1) 6 const int N = 530000<<1;//zkw线段树只能查询(0,bit),所以只有bit-2个叶节点,bit-2<n

[模板]树状数组2

https://www.luogu.org/problemnew/show/P3368 1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 using namespace std; 5 #define lowbit(a) (a&(-a)) 6 7 int n, m, t[500010], bas[500010]; 8 9 inline void update(int x, int

[模板]树状数组

OJ题号:洛谷P3374 1 #include<cstdio> 2 #include<cstring> 3 #define maxn 500000 4 int n,m; 5 struct BIT { 6 int val[maxn]; 7 BIT() { 8 memset(val,0,sizeof val); 9 } 10 int lowbit(int x) { 11 return x&-x; 12 } 13 void modify(int p,const int x) {

浅析树状数组

目录 beginning 顺序结构 A+B 高精 A+B 压位高精 A+B 二分A+B 树状数组简介(不喜欢啰嗦的请直接跳到这里) 基础概念 代码实现 大体结构 lowbit lowbit的作用 总结+代码 逆序对 离散化 方式 实现 代码 树状数组进阶 差分 区间修改+单点查询 主要思想 单点查询 区间修改 区间修改+区间查询 差分分析 代码 2D树状数组 query update 区间修改+单点查询 区间修改+区间查询 时间复杂度 罗列例题 一维 beginning 顺序结构 A+B 高精

树状数组的原理和基础应用

这样的数据结构称作树状数组,它支持O(logN)的单点修改和区间查询,效率高并且代码简洁,缺点在于适用范围不如线段树广.不难看出(雾),tree[i]表示a[i]及之前的 lowbit(i)个 数,定义lowbit(i)等于取i的二进制中最后一个'1'表示的大小观察发现(.),修改a[i]只需更新包含i的节点,倒推可知从i开始,每次把i加上lowbit(i),这些节点包含了a[i]从i开始,每次把i减去lowbit(i)直到为0,这些节点的值加起来就是前缀和.例题1:树状数组1  https:/

回顾树状数组

树状数组是一种常用的数据结构,能够在O(log2n)的时间内进行单点修改和求前缀和.因为代码量小.常熟小往往在某些应用中快于线段树(当然有些问题是不能呢用树状数组完成的). 最基本的树状数组 方法1:用一个数组,O(1)修改, O(n)查询 方法2:求前缀和,O(n)修改,O(1)查询 以上两种方法卡一卡就TLE了. 树状数组就平衡了一下这两种方法,修改的时候多修改一点,查询的时候多算一点. 为了清楚地明白树状数组是如何运作的,我们实现定义 lowbit(x) 是写成2进制后的x中最后一位1.例