差分数列+树状数组

差分数列+树状数组:可以把树状数组的“单点修改,区间查询”-->改变为“区间修改和单点查询”

例题:

codevs 1081 线段树练习 2

时间限制: 1 s

空间限制: 128000 KB

题目等级 : 大师 Master

题目描述 Description

给你N个数,有两种操作

1:给区间[a,b]的所有数都增加X

2:询问第i个数是什么?

输入描述 Input Description

第一行一个正整数n,接下来n行n个整数,再接下来一个正整数Q,表示操作的个数. 接下来Q行每行若干个整数。如果第一个数是1,后接3个正整数a,b,X,表示在区间[a,b]内每个数增加X,如果是2,后面跟1个整数i, 表示询问第i个位置的数是多少。

输出描述 Output Description

对于每个询问输出一行一个答案

样例输入 Sample Input

3

1

2

3

2

1 2 3 2

2 3

样例输出 Sample Output

5

数据范围及提示 Data Size & Hint

数据范围

1<=n<=100000

1<=q<=100000

代码:

#define N 100100
#include<iostream>
#include<cstdio>
using namespace std;
#include<cstring>
int a[N],b[N],n,q,l,r,x,p;
long long  tree[N];
void build_tree(int k,int m)
{
    while(k<=n)
    {
        tree[k]+=m;
        k+=((-k)&k);
    }
}
long long query(int k)
{
    long long ans=0;
    while(k)
    {
        ans+=tree[k];
        k-=((-k)&k);
    }
    return ans;
}
void input()
{
    scanf("%d",&n);
    a[0]=0;
    for(int i=1;i<=n;++i)
    {
        scanf("%d",&a[i]);
        b[i]=a[i]-a[i-1];
        build_tree(i,b[i]);
    }
}
int main()
{
    input();
    scanf("%d",&q);
    for(int i=0;i<q;++i)
    {
        scanf("%d",&x);
        if(x==1)
        {
            scanf("%d%d%d",&l,&r,&p);
            build_tree(l,p);
            build_tree(r+1,-p);
        }
        else
        {
            scanf("%d",&p);
            cout<<query(p)<<endl;
        }
    }
    return 0;
}
时间: 2024-10-10 07:06:57

差分数列+树状数组的相关文章

树状数组与差分

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

【线段树】【树状数组】【CF 121E】幸运数列

1922. [CF 121E]幸运数列 ★★★ 输入文件:cf121e.in 输出文件:cf121e.out 简单对比 时间限制:3 s 内存限制:256 MB [题目描述] 对于欧洲人来说,"幸运数"是指那些十进制只由4或7组成的数.财务员Petya需要维护一个支持如下操作的整数数列: add l r d - 表示将[l, r]区间内的所有数加上一个正整数d(). count l r - 统计[l, r]区间内有多少个"幸运数".() 请你帮助Petya实现它.

bzoj2743: [HEOI2012]采花--离线树状数组+差分

题目大意:给定一个区间,查询子区间里出现次数不小于二的数的个数 此题想了好久没想出来,后来是在网上学习的一个方法 首先按查询区间的右端点进行排序,按右端点从小到大处理 假设pre[a[i]]是与a[i]相同的前一个数的位置,记为left[i] 当查询到第i个数时,对left[left[i]]+1~left[i]的每个数的权值w[]加1 也就是说:左端点在left[left[i]]+1~left[i]内,右端点为i的区间里,出现次数不小于二的数+1 那么对于查询i,答案就是w[left[i]] 因

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

树状数组区间修改,区间更新:差分数组的运用

树状数组最原始的作用就是求前缀和,可以实现单点修改和区间查询. 但是假设现在有: 1.区间修改,单点查询 2.区间修改,区间查询 但是又不想敲线段树怎么办? 就用树状数组喽. 假设现在有一个原数组a(假设a[0] = 0),有一个数组d,d[i] = a[i] - a[i-1],那么 a[i] = d[1] + d[2] + .... + d[i] d数组就是差分数组 所以求a[i]就可以用树状数组维护d[i]的前缀和 区间修改,单点查询: 根据d的定义,对[l,r]区间加上x,那么a[l]和a

差分+树状数组【p4868】Preprefix sum

Description 前缀和(prefix sum)\(S_i=\sum_{k=1}^i a_i\). 前前缀和(preprefix sum) 则把\(S_i\)作为原序列再进行前缀和.记再次求得前缀和第i个是\(SS_i\) 给一个长度n的序列\(a_1, a_2, \cdots, a_n\)有两种操作: Modify i x:把\(a_i\)改成\(x\): Query i:查询\(SS_i\) Input 第一行给出两个整数N,M.分别表示序列长度和操作个数 接下来一行有N个数,即给定的

bzoj3132 上帝造题的七分钟(差分+二维树状数组)

bzoj3132 上帝造题的七分钟(差分+二维树状数组) Time Limit: 20 Sec Memory Limit: 128 MB Description "第一分钟,X说,要有矩阵,于是便有了一个里面写满了0的n×m矩阵. 第二分钟,L说,要能修改,于是便有了将左上角为(a,b),右下角为(c,d)的一个矩形区域内的全部数字加上一个值的操作. 第三分钟,k说,要能查询,于是便有了求给定矩形区域内的全部数字和的操作. 第四分钟,彩虹喵说,要基于二叉树的数据结构,于是便有了数据范围. 第五分

POJ2155/LNSYOJ113 Matrix【二维树状数组+差分】【做题报告】

这道题是一个二维树状数组,思路十分神奇,其实还是挺水的 题目描述 给定一个N∗NN∗N的矩阵AA,其中矩阵中的元素只有0或者1,其中A[i,j]A[i,j]表示矩阵的第i行和第j列(1≤i,j≤N)(1≤i,j≤N),初始矩阵元素都是0.在矩阵上进行TT次操作,操作有以下两种: (1)格式为C x1 y1 x2 y2(1≤x1≤x2≤n,1≤y1≤y2≤n)C x1 y1 x2 y2(1≤x1≤x2≤n,1≤y1≤y2≤n) ,其中CC为字符“C”,表示把以(x1,y1)(x1,y1)为左上角,

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

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