树状数组的原理在这里就不讲解了,这里讲解树状数组的几个应用。一提到树状数组,很多人就会想到线段树,凡是可以使用树状数组解决的问题, 使用线段树一定可以解决, 但是线段树能够解决的问题树状数组未必能够解决。线段树适用于:单点修改区间查询,区间修改单点查询,区间修改区间查询。这里的修改是增加某个数或者减少某个数,不适合替换成某个数。
具体讲解:https://www.cnblogs.com/RabbitHu/p/BIT.html
单点修改 + 区间查询
1080 线段树练习
链接:http://codevs.cn/problem/1080/
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int c[100001];
int n, m;
int lowbit(int a){
return a & (- a);
}
void add(int pos, int val){
for(int i = pos; i <= n; i += lowbit(i)){
c[i] += val;
}
}
int sum(int pos){
int res = 0;
for(int i = pos; i > 0; i -= lowbit(i)){
res += c[i];
}
return res;
}
int main(){
cin>>n;
int t1, t2, t3, s;
for(int i = 1; i <= n; i++){
cin>>s;
add(i, s);
}
cin>>m;
while(m--){
cin>>t1>>t2>>t3;
if(t1 == 1){
add(t2, t3);
}
else {
cout<<sum(t3) - sum(t2 - 1)<<endl;
}
}
return 0;
}
区间修改 + 单点查询
1081 线段树练习 2
链接:http://codevs.cn/problem/1081/
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int c[500001];
int n, m;
int lowbit(int a){
return a & (- a);
}
void add(int pos, int val){
for(int i = pos; i <= n; i += lowbit(i)){
c[i] += val;
}
}
void add_range(int l, int r, int val){
add(l, val);
add(r + 1, -val);
}
int sum(int pos){
int res = 0;
for(int i = pos;i > 0; i -= lowbit(i)){
res += c[i];
}
return res;
}
int main(){
cin>>n;
int t1, t2, t3, t4, s, pre = 0;
for(int i = 1; i <= n; i++){
cin>>s;
add(i, s - pre);
pre = s;
}
cin>>m;
while(m--){
cin>>t1;
if(t1 == 1){
cin>>t2>>t3>>t4;
add_range(t2, t3, t4);
}
else {
cin>>t2;
cout<<sum(t2)<<endl;
}
}
return 0;
}
区间修改 + 区间查询
1082 线段树练习 3
链接:http://codevs.cn/problem/1082/
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
#define ll long long
ll c[200001], c1[200001];
int n, m;
int lowbit(int a){
return a & (- a);
}
void add(int pos, ll val){
for(int i = pos; i <= n; i += lowbit(i)){
c[i] += val;
c1[i] += val * pos;
}
}
void add_range(int l, int r, ll val){
add(l, val);
add(r + 1, -val);
}
ll sum(int pos){
ll res = 0;
for(int i = pos; i > 0; i -= lowbit(i)){
res += ((pos + 1) * c[i] - c1[i]);
}
return res;
}
ll sum_range(int l, int r){
return sum(r) - sum(l- 1);
}
int main(){
cin>>n;
int t1, t2, t3;
ll t4, s, pre = 0;
for(int i = 1; i <= n; i++){
cin>>s;
add(i, s - pre);
pre = s;
}
cin>>m;
while(m--){
cin>>t1;
if(t1 == 1){
cin>>t2>>t3>>t4;
add_range(t2, t3, t4);
}
else {
cin>>t2>>t3;
cout<<sum_range(t2, t3)<<endl;
}
}
return 0;
}