实战演练
1.【模板】树状数【模板】树状数组1
输入:
5 5
1 5 4 2 3
2 2 4
1 2 3 2
2 3 4
1 1 5 1
2 1 4
注意:只修改一个数(单点修改),却要输出一个区间的值(区间查询)!!!
解法一:线段树
#include<bits/stdc++.h> //线段树
using namespace std;
const int N = 5e5+5;
int n,m,ans;
int he=0;
int input[N];
struct node { //结构体,left,right表示input[left]~input[right]的范围,从left开始,到right结束,tree.num表示他们之间的和int left,right;int num;
} tree[2000010];
void build(int left,int right,int index) { //创建线段树he++;tree[index].left=left;tree[index].right=right;if(left==right)return ;int mid=(right+left)/2;build(left,mid,index*2);build(mid+1,right,index*2+1);
}
int add(int index) { //输入时候的tree数组,tree[i]=tree[2*i]+tree[2*i+1]if(tree[index].left==tree[index].right) {//cout<<index<<" "<<input[tree[index].right]<<endl; //验证tree[index].num=input[tree[index].right];return tree[index].num;}tree[index].num=add(index*2)+add(index*2+1);return tree[index].num;
}
void my_plus(int index,int dis,int k) { //区间修改tree[index].num+=k;if(tree[index].left==tree[index].right)return ;if(dis<=tree[index*2].right)my_plus(index*2,dis,k);if(dis>=tree[index*2+1].left)my_plus(index*2+1,dis,k);
}
void search(int index,int l,int r) { //计算数组input数组l到r的和//cout<<index<<" ";if(tree[index].left>=l && tree[index].right<=r) {ans+=tree[index].num;return ;}if(tree[index*2].right>=l)search(index*2,l,r);if(tree[index*2+1].left<=r)search(index*2+1,l,r);
}
int main() {cin>>n>>m;for(int i=1; i<=n; i++)cin>>input[i];build(1,n,1);add(1);for(int i=1; i<=m; i++) {int a,b,c;scanf("%d%d%d",&a,&b,&c);if(a==1) {my_plus(1,b,c);} else {ans=0;search(1,b,c);printf("%d\n",ans);}}return 0;
}
解法二:树状数组
2.【模板】树状数组2
输入:
5 5
1 5 4 2 3
1 2 4 2
2 3
1 1 5 -1
1 3 5 7
2 4
注意:只修改一个区间(区间修改),却只要输出一个位置的值(单点查询)!!!
方法一:线段树
方法二:树状数组