线段树与树状数组-基础

线段树与树状数组

  学之前感觉这是两个非常非常难的数据结构,学完才发现也没有想象中那么难,但是题可以出的非常难。

  这里就有一些同学坚持认为树状数组没有用,其实树状数组虽然功能少一点,却也是很有优势的。1.常数小;2.代码短;3.内存小;

  翻了翻学习资料的文件夹,发现关于这两个数据结构的课件还是比较多的,难度分布也非常的广泛...


 

   树状数组的常规用法:

  
1 void add (int x,int a)
2 {
3     while (x<=n)
4     {
5         c[x]+=a;
6         x+=lowbit(x);
7     }
8 }
add
  
 1 int sum(int x)
 2 {
 3     int S=0;
 4     while(x!=0)
 5     {
 6         S+=c[x];
 7         x-=lowbit(x);
 8     }
 9     return S;
10 }
sum

   初始化一般是一个一个的加,但是其实还有一种方法可以达到$O(N)$的复杂度,非常优越。

  
 1 void init()
 2 {
 3     memset(c,0,sizeof(c));
 4     for (R i=1;i<=n;++i)
 5     {
 6         c[i]+=a[i];
 7         if(i+lowbit(i)<=n)
 8             c[i+lowbit(i)]+=c[i];
 9     }
10 }
init

   树状数组有一个特别好的用途就是二维树状数组,二维线段树的代码复杂度比一般线段树要大不少,但是二维树状数组只多两行而已。

  
1 void add(int v,int x,int y)
2 {
3     for (R i=x;i<=n;i+=lowbit(i))
4         for (R j=y;j<=m;j+=lowbit(j))
5             t[i][j]+=v;
6 }
add
  
1 int ask(int x,int y)
2 {
3     int ans=0;
4     for (R i=x;i;i-=lowbit(i))
5         for (R j=y;j;j-=lowbit(j))
6             ans+=t[i][j];
7     return ans;
8 }
ask

  补充一个内容,二维前缀和:

  $X_{1},X_{2},Y_{1},Y_{2}(X_{1}<=X_{2},Y_{1}<=Y_{2}) $区域的和:$S=a[X_2][Y_2]-a[X_1-1][Y_2]-a[X_2][Y_1-1]+a[X_1-1][Y_1-1]$

   

猜你喜欢

转载自www.cnblogs.com/shzr/p/9247096.html
今日推荐