树状数组2题解

题目描述:
给定一个长度为 n 的序列 {an},给出 m 次操作,操作有两种:
1 l r x,表示 al 到 ar 都加 x;
2 p,表示查询 ap 的值。
输入格式:
第一行包含两个正整数 n 和 m。
第二行包含 n 个数,表示 a1 到 an。
接下来 m 行,每行一个操作,操作一定为 1 l r x 或者 2 p 的形式。
输出格式:
对于每一个 2 操作,输出一行一个整数,表示查询的结果。
样例输入:
5 3
5 4 3 2 1
2 4
1 2 4 -3
2 4
样例输出:
2
-1
数据规模:
对于 60% 的数据,n,m≤1000。
对于 100% 的数据,2≤n≤105,1≤m≤105,|ai|≤1000,|x|≤1000。

这里我们先拓展一下树状数组:树状数组 - OI Wiki
这道题由于是一道模版题,所以线段树基本的函数就如下

int lowbit(int x){
	return x&-x;
}
int get_sum(int x){
	int res=0;
	for(int i=x;i>0;i-=lowbit(i)){
		res+=c[i];
	}
	return res;
}
int get_sum(int l,int r){
	return get_sum(r)-get_sum(l-1);
}
void add(int x,int v) {
    for(int i=x;i<=n;i+=lowbit(i)){
        c[i]+=v;
    }
}

你以为这道题这么简单,结果老师讲的时候才发现需要差分(⊙o⊙)…


signed main(){
    cin>>n>>q;
    for(int i=1;i<=n;i++){
        输入
    	b[i]=a[i]-a[i-1];差分
	}
	for(int i=1;i<=n;i++){
		add(i,b[i]);
	}
	for(int i=1,op;i<=q;i++){
		cin>>op;
		if(op==1){判断这总没问题吧
			int l,r,x;
			cin>>l>>r>>x;
			add(l,x);
			add(r+1,-x);
		}
		else{
			int x;
			cin>>x;
			cout<<get_sum(x)<<endl;
		}
	}
    return 0;
}

如果你发现把这些代码平起来还没AC
你就得看一下要不要开long long了
最后一句总结
十年OI一场空,不开long long见祖宗

3 个赞

这不是线段树模板题(doge

1 个赞

骗分过样例,打表出省一