luogu3368树状数组模板2

题目链接:https://www.luogu.org/problemnew/show/P3368

题意:与模板1不同的是这题的操作是树状数组并不在行的区间更新和单点查找,如果按照模板1那样写肯定会T。但这题题目是树状数组模板,所以肯定还是能用树状数组来做的,我用a数组保存原数组,tr数组表示树状数组。

进行区间更新update时,只需要将组成这个区间的几个大管辖节点加这个数(类似于线段树中的懒操作)。

查询的时候,依层找自己的上级,然后加上自己上级的值就行了。因为在这里,上级的值就相当于懒操作的值。

具体可以找组数据模拟一下,就懂了,这样做的复杂度同树状数组一样,但tr数组已经不是定义上的树状数组了,我们只是借用了树状数组这一数据结构。

AC代码:

#include<cstdio>
#include<cctype>
using namespace std;

inline int read(){
    int x=0,f=0;char c=0;
    while(!isdigit(c)){f|=c=='-';c=getchar();}
    while(isdigit(c)){x=(x<<3)+(x<<1)+(c^48);c=getchar();}
    return f?-x:x;
}

int a[500005],tr[500005],n,m;

int lowbit(int x){
    return x&(-x);
}

void update(int x,int k){
    while(x>0){
        tr[x]+=k;
        x-=lowbit(x);
    }
}

int query(int x){
    int ans=0;
    while(x<=n){
        ans+=tr[x];
        x+=lowbit(x);
    }
    return ans;
}

int main(){
    n=read(),m=read();
    for(int i=1;i<=n;++i)
        a[i]=read();
    while(m--){
        int op=read();
        if(op==1){
            int x=read(),y=read(),k=read();
            update(y,k);
            update(x-1,-k);
        }            
        else{
            int x=read();
            printf("%d
",a[x]+query(x));
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/FrankChen831X/p/10797473.html