线段树是OI中特别重要的数据结构部分,这里提供了三种此题的模板,以供大家参考。
1.树状数组:
优点:空间复杂度小,实现容易。
缺点:操作少,有些时候难以用上。
注意:lowbit函数用来保存2进制的最后一位1,然后还要用到前缀和思想。
树状数组:
#include <cstdio>
using namespace std;
const int maxx = 500000 + 100;
int tree[maxx];
int n,m,Flag,x,s,t;
int lowbit(int x){
return x&(-x);
}
void Add(int i,int k){
for(i;i<=n;i+=lowbit(i))
tree[i] += k;
}
int Query(int k){
int ans = 0;
for(int i=k;i;i-=lowbit(i)) ans += tree[i];
return ans;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&x),Add(i,x);
scanf("%d",&m);
while( m-- ){
scanf("%d%d%d",&Flag,&s,&t);
if(Flag==1) Add(s,t);
if(Flag==2) printf("%d\n",Query(t)-Query(s-1));
}
return 0;
}
2.线段树:
优点:操作多,易理解。
缺点:实现麻烦,空间较大。
注意:这种线段树一定要会打,应用非常广。
线段树:....
....................
代码找不到了QvQ....
3.zkw线段树:
由清华大学zkw发明,可以百度《统计的力量》。
优点:代码短易实现,非递归,效率高。
缺点:难以真正理解。
zkw线段树:
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int Size = (1<<19);
int Node[Size];
int n,m,x,y,num;
int M,Flag;
void Update(int i,int k){
for(Node[i+=M] += k,i>>=1 ; i ; i >>= 1)
Node[i]=Node[i<<1]+Node[i<<1|1];
}
void Query(int x,int y){
int ans = 0;
for( x=x+M-1 , y=y+M+1 ; x^y^1 ; x >>= 1 , y >>= 1){
if(~x&1) ans += Node[x^1];
if(y&1) ans += Node[y^1];
}
printf("%d\n",ans);
}
int main(){
scanf("%d",&n);
for(M=1;M<n+2;M<<=1);
for(int i=1;i<=n;i++)
scanf("%d",&num),Update(i,num);
scanf("%d",&m);
while( m-- ){
scanf("%d%d%d",&Flag,&x,&y);
if(Flag==1) Update(x,y);
if(Flag==2) Query(x,y);
}
return 0;
}