树状数组模板

0x00 前言

(我说我在快睡着的情况下写了个这你信吗

0x01 区间查询

#include<bits/stdc++.h>
#define int long long//跟同机房大佬学到的,懒到无可救药时可以写写,考试时千万别 
using namespace std;

const int N=5000100;
int n,m;
int tree[N];

int read(){
	int x=0,y=1;
	char c=getchar();
	while(c<'0'||c>'9'){
		if(c=='-')
			y=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9'){
		x=x*10+c-'0';
		c=getchar();
	}
	return x*y;
}

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

void add(int x,int y){
    while(x<=n){
        tree[x]+=y;
        x+=lowbit(x);
    }
}

int sum(int x){
    int ans=0;
    while(x!=0){
        ans+=tree[x];
        x-=lowbit(x);
    }
    return ans;
}

signed main(){
    n=read();
    m=read();
    for(int i=1;i<=n;i++){
        int a;
        a=read();
        add(i,a);
    }
    for(int i=1;i<=m;i++){
        int a,b,c;
        a=read();
        b=read();
        c=read();
        if(a==1)
            add(b,c);
        else
            printf("%d\n",sum(c)-sum(b-1));
    }
    return 0;
}

这也是\(P3374\)的正解

0x02 单点查询

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;

const int N=10000010;
ll n,m,q,x,y,k;
ll sig[N],tree[N];

ll read(){
	ll x=0,y=1;
	char c=getchar();
	while(c<'0'||c>'9'){
		if(c=='-')
			y=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9'){
		x=x*10+c-'0';
		c=getchar();
	}
	return x*y;
}

ll lowbit(ll num){
	return num&-num;
}

void add(ll k,ll num){
	for(ll i=k;i<=n;i+=lowbit(i))
		tree[i]+=num;
}

ll ask(ll k){
	ll ans=0;
	for(ll i=k;i>=1;i-=lowbit(i))
		ans+=tree[i];
	return ans;
}
int main(){
	n=read();
	m=read();
	for(int i=1;i<=n;i++)
		sig[i]=read();
	for(int i=1;i<=m;i++){
		q=read();
		if(q==1){
			x=read();
			y=read();
			k=read();
			add(x,k);
			add(y+1,-k);
		}
		if(q==2){
			x=read();
			printf("%lld\n",sig[x]+ask(x));
		}
	}
	return 0;
}

这也是\(P3368\)的正解

posted @ 2021-07-14 19:28  BFNewdawn  阅读(24)  评论(0编辑  收藏  举报