洛谷 P3368 【模板】树状数组 2

目录:

题意:

给出两种操作:一个是对指定区间每个数进行加法,另个是求指定数当前的值

分析:

这题其实跟P3367是差不多的
但是需要用到差分:
来介绍一下差分
设数组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];(这个很好证的)。
假如区间[2,4]都加上2的话
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]是不变的
所以对区间[x,y]进行修改,只用修改b[x]与b[y+1]:
b[x]=b[x]+k;b[y+1]=b[y+1]-k
而我们对区间进行加法,设是给x~y加w,那我们其实是对1~x加w,而对x+1~y减w,最后输出的话,跟P3367相差无几

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#define LL long long
using namespace std;
inline LL read() {
    LL d=0,f=1;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
    return d*f;
}
int c[500001];
int n=read(),m=read();
int lowbit(int x)
{
    return x&(-x);
}
void change(int k,int delta)
{
    while(k<=n)
    {
        c[k]+=delta;
        k+=lowbit(k);
    }
    return;
}
int t;
int getsum(int k)
{
    t=0;
    while(k>0)
    {
        t+=c[k];
        k-=lowbit(k);
    }
    return t;
}
int main()
{
    int tf,x,y,ago=0,w;
    for(int i=1;i<=n;i++) 
    {
        w=read();
        change(i,w-ago);//跟分析一样
        ago=w;
    }
    for(int i=1;i<=m;i++)
    {
        tf=read();
        if(tf==1)
        {   
            x=read();y=read();w=read();
            change(y+1,-w);//跟小编分析的同理
            change(x,w);
        }
        else
        {
            x=read();
            printf("%d\n",getsum(x));//直接求解
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_35786326/article/details/80270044