P3368 【模板】树状数组 2 (树状数组维护差分数组)

题目连接: 【模板】树状数组 2
写这个题是打算学习差分的,所以就没写线段树和树状数组。

差分

来自: Snitro

a [   ] = { 1 , 6 , 8 , 5 , 10 } b [   ] = { 1 , 5 , 2 , 3 , 5 } 设数组a[\ ]=\{1,6,8,5,10\},那么差分数组b[\ ]=\{1,5,2,-3,5\}

b [ i ] = a [ i ] a [ i 1 ] ( a [ 0 ] = 0 ) , a [ i ] = b [ 1 ] + . . . . + b [ i ] 也就是说b[i]=a[i]-a[i-1] (a[0]=0),那么a[i]=b[1]+....+b[i] (这个很好证的)。

[ 2 , 4 ] 2 假如区间[2,4]都加上2的话

a a [   ] = { 1 , 8 , 10 , 7 , 10 } b b [   ] = { 1 , 7 , 2 , 3 , 3 } ; a数组变为a[\ ]=\{1,8,10,7,10\},b数组变为b[\ ]=\{1,7,2,-3,3\};

b b [ 2 ] b [ 5 ] [ 2 , 4 ] 2 , b [ i ] b [ i 1 ] . 发现了没有,b数组只有b[2]和b[5]变了,因为区间[2,4]是同时加上2的,所以在区间内b[i]-b[i-1]是不变的.

[ x , y ] , b [ x ] b [ y + 1 ] : 所以对区间[x,y]进行修改,只用修改b[x]与b[y+1]:

b [ x ] = b [ x ] + k ; b [ y + 1 ] = b [ y + 1 ] k ; b[x]=b[x]+k;b[y+1]=b[y+1]-k;

然后我照着写了一发 T 了。。。
然后又看到下面有人用树状数组维护差分数组

AC code
/*
【模板】树状数组 2
P3368
https://www.luogu.org/problem/P3368
解法: 树状数组维护差分数组
*/
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define maxn 1000000
ll a[maxn];
ll tree[maxn<<1];
ll n,m;
inline long long read()//快读
{
    long long x=0,f=1;char c=getchar();
    while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
    while(isdigit(c)){x=x*10+c-48;c=getchar();}
    return x*f;
}
void update(int x,int val){
	while(x<=n){
		tree[x]+=val;
		x+=x&(-x);
	}
}
long long sum(long long x){
	long long ans=0;
	while(x>=1){
		ans+=tree[x];
		x-=x&(-x);
	}
	return ans;
}
int main(){
  int s,l,r,x;
  n=read();
  m=read();
  memset(tree,0,(n+1)*sizeof (ll));
  for(int i=1;i<=n;i++){
    a[i]=read();
    update(i,a[i]-a[i-1]);
  }
  while(m--){
    s=read();
    if(s==2){
      x=read();
      printf("%lld\n", sum(x));
    }else{
      l=read();
      r=read();
      x=read();
      update(l,x);
      update(r+1,-x);
    }
  }
}
发布了70 篇原创文章 · 获赞 22 · 访问量 6497

猜你喜欢

转载自blog.csdn.net/weixin_44410512/article/details/102301152