差分+树状数组【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\)有两种操作:

  1. Modify i x:把\(a_i\)改成\(x\);
  2. Query i:查询\(SS_i\)

Input

第一行给出两个整数N,M。分别表示序列长度和操作个数

接下来一行有N个数,即给定的序列a1,a2,....an

接下来M行,每行对应一个操作,格式见题目描述

Output

对于每个询问操作,输出一行,表示所询问的SSi的值。

显然,这是差分+树状数组

题目中给定的\(a_i\)就是我们的差分数组。

不会差分的小伙汁,来这里

安利很好的写树状数组的博客.

然后推一下式子.

如果我们修改差分数组\(a_i\),显然,\(S_i\)会变化.

\(S_i=S_{i-1}+a_i\)

现在变成了

\(S_i=S_{i-1}+x\)

那么差值就变成了\(x-a_i\)

那么,我们就\(add(i,x-a[i])\),不要忘了最后将\(a_i\)变为\(x\)

代码

#include<cstdio>
#include<algorithm>
#include<iostream>
#define int long long
#define R register
using namespace std;
inline void in(int &x)
{
    int f=1;x=0;char s=getchar();
    while(!isdigit(s)){if(s=='-')f=-1;s=getchar();}
    while(isdigit(s)){x=x*10+s-'0';s=getchar();}
    x*=f;
}
int n,m,last,t1[1000008],t2[1000008],a[1000008];
#define lowbit(x) x&-x
inline void add(int pos,int x)
{
    for(R int i=pos;i<=n;i+=lowbit(i))
        t1[i]+=x,t2[i]+=pos*x;
}
inline int query(int pos)
{
    R int res=0;
    for(R int i=pos;i;i-=lowbit(i))
        res+=t1[i]*(pos+1)-t2[i];
    return res;
}
char opt[8];
signed main()
{
    in(n),in(m);
    for(R int i=1,x;i<=n;i++)
    {
        in(a[i]);
        add(i,a[i]);
    }
    for(R int i=1,x,y;i<=m;i++)
    {
        scanf("%s",opt+1);
        if(opt[1]=='Q')
        {
            in(x);
            printf("%lld\n",query(x));
        }
        else
        {
            in(x),in(y);
            add(x,y-a[x]);
            a[x]=y;
        }
    }
}

原文地址:https://www.cnblogs.com/-guz/p/9858504.html

时间: 2024-07-29 08:27:33

差分+树状数组【p4868】Preprefix sum的相关文章

2018年四校联合周赛-第二场 B.异或和问题(二维树状数组)

异或和问题 TimeLimit:1000MS  MemoryLimit:256MB 64-bit integer IO format:%I64d Problem Description 现在有一个n行n列的矩阵.初始状态下,矩阵里的所有值都为0.行的编码是从1到n,列的编码也同样是从1到n. ai,?j.是在第i行第j列的数.子矩阵(x0, y0, x1, y1)是由ai,?j. (x0?≤?i?≤?x1, y0?≤?j?≤?y1)组成的矩阵. 现在需要进行下列的两个操作:       1.查询

初学树状数组

原理: 有好的博客做讲解了(见参考文章),这里暂时略过,如果以后有新的理解和体会会再来写的.(应该不会) 思想: 这里可以把树状数组的精妙之处提一下(我理解的) 首先,树状数组之所以叫树状数组,因为它像树一样,有类似树的父子节点关系,这点在更新和求和操作上体现的最为明显.而最终也只是数组,因为实现起来简单方便,如数组一样.(一开始还纳闷为什么不叫二进制索引树),英文名BIT(Binary Index Tree).这个数据结构实现的功能像线段树一样,两者有着异曲同工之妙. 其次,树状数组的神奇之处

树状数组模板--Color the ball

Color the ball HDU - 1556 N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <= b),lele便为骑上他的“小飞鸽"牌电动车从气球a开始到气球b依次给每个气球涂一次颜色.但是N次以后lele已经忘记了第I个气球已经涂过几次颜色了,你能帮他算出每个气球被涂过几次颜色吗? Input 每个测试实例第一行为一个整数N,(N <= 100000).接下来的N行,每行包括2个整数a b(1 <= a <= b <

Gym 100960G (set+树状数组)

Problem Youngling Tournament 题目大意 给一个序列a[i],每次操作可以更改一个数,每次询问 将序列排序后有多少个数a[i]>=sum[i-1]. n<=10^5,q<=5*10^4,a[i]<=10^12 解题分析 可以发现,在最优情况下,该序列长度最多为logn. 将询问离线后,用multiset来维护a[i],用树状数组来维护sum[i].树状数组所存下标为离散化后的a[i]. 每次查询时跳跃式地在set中查找. 时间复杂度 O((n+m)log(

hdu 1556 Color the ball (扫描线+树状数组)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1556 Color the ball Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 14237    Accepted Submission(s): 7120 Problem Description N个气球排成一排,从左到右依次编号为1,

hdu5293 lca+dp+树状数组+时间戳

题意是给了 n 个点的树,会有m条链条 链接两个点,计算出他们没有公共点的最大价值,  公共点时这样计算的只要在他们 lca 这条链上有公共点的就说明他们相交 dp[i]为这个点包含的子树所能得到的最大价值 sum[i]表示这个点没有选择经过i这个点链条的总价值 两种选择 这个点没有被选择 dp[i]=sum[i]=sigma(dp[k])k为i的子树 选择了某个链 假设这条链 为(tyuijk) 那么dp[i]=(sum[i]-dp[u]-dp[j])+(sum[j]-dp[k])+dp[k]

codeforces 570 D. Tree Requests 树状数组+dfs搜索序

链接:http://codeforces.com/problemset/problem/570/D D. Tree Requests time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output Roman planted a tree consisting of n vertices. Each vertex contains a low

poj2299(Ultra-QuickSort)树状数组+离散化

题目就是让你求逆序数,用树状数组很简单,不过数据太大,要先进行离散化,将数据范围压缩到1~n以内.还有poj竟然不支持c++11,害得我lambda表达式编译错误. #include <iostream> #include <sstream> #include <fstream> #include <string> #include <map> #include <vector> #include <list> #incl

SUOI08 一收一行破 (lca+树状数组)

用一个差分树状数组维护一下每个深度的和,然后每次拿着路径端点和lca加一加减一减就行了 1 #include<bits/stdc++.h> 2 #define pa pair<int,int> 3 #define ll long long 4 using namespace std; 5 const int maxn=200020; 6 7 inline ll rd(){ 8 ll x=0;char c=getchar();int neg=1; 9 while(c<'0'||