博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
树状数组
阅读量:4561 次
发布时间:2019-06-08

本文共 3377 字,大约阅读时间需要 11 分钟。

这是一种实用并且代码极短的高级数据结构。

能在O(lgn)内完成修改,和询问。解决了普通数组的询问长,前缀和的修改长的问题。

它提供两种操作:

  • 将A[i]叫上D;
  • 求出A[i]的前缀和。

那么怎么实现呢?

我们新增一个数组c[],其中c[i]=A[i-2^k+1]+……+A[i](k为i在二进制形式下末尾0的个数)。

那怎么求出2^k呢,我们就可以用lowbit(i),lowbit(i)=i&(-i);

首先是修改操作,将所有包含它的数都加上要加的数。

1 void add(int x){2     for (int i=x;i<=N;i+=lowbit(i)) c[i]++;3 }
View Code

求和就是把它未包含的数加上。

1 long long sum(int x){2     long long Sum=0;3     for (int i=x;i>0;i-=lowbit(i)) Sum+=c[i];4     return Sum;5 }
View Code

这就是基本的树状数组了。

接下来是一些基本的求和模型。

1.改点求段:

  修改操作:将A[x]的值加上v;

  求和操作:求此时A[l..r]的和。

十分简单:

1 void add(int x){2     for (int i=x;i<=N;i+=lowbit(i)) c[i]++;3 }4 long long sum(int x){5     long long Sum=0;6     for (int i=x;i>0;i-=lowbit(i)) Sum+=c[i];7     return Sum;8 }
View Code

  修改操作:add(x,v);

  求和操作:sum(r)-sum(l-1);

s2.改段求点:

  修改操作:将A[l..r]之间的全部元素值加上v;

  求和操作:求此时A[x]的值。

这回就用差分法A[i]表示原意义一下的A[i]-A[i-1];

1 void add(int x){2     for (int i=x;i<=N;i+=lowbit(i)) c[i]++;3 }4 long long sum(int x){5     long long Sum=0;6     for (int i=x;i>0;i-=lowbit(i)) Sum+=c[i];7     return Sum;8 }
View Code

  修改操作:add(l,v),add(r+1,-v);

  求和操作:sum(x);

3.改段求段:

  修改操作:将A[l..r]之间的全部元素值加上v;

  求和操作:求此时A[l..r]的和。

关于这种模型需要一个辅助数组:存(当前位置-1)*v的值。

因为Sum(1,x)在差分意义下是(Sigma(i<=x)(A[i]*(x-(i-1))))

做出A[i]*(i-1)的辅助数组就可以了。

1 void Add(ll *T,int x,ll v){ 2     for (int i=x;i<=n;i+=lowbit(i)) T[i]+=v;  3 } 4 void Update(ll a,ll b,ll c){ 5     Add(T1,a,c); Add(T1,b+1,-c); 6     Add(T2,a,(a-1)*c); Add(T2,b+1,b*(-c)); 7 } 8 ll Sum_(ll *T,int x){ 9     ll ans=0;10     for (int i=x;i>0;i-=lowbit(i)) ans+=T[i];11     return ans;12 }13 ll Sum(int a,int b){14     ll tot=(a-1)*(Sum_(T1,a-1))-Sum_(T2,a-1);15     ll tot_=(b)*(Sum_(T1,b))-Sum_(T2,b);16     return tot_-tot;17 }
View Code

  修改操作:模板内Update;

  求和操作:模板内Sum;

还有二维树状数组的使用,

1 int sum(int x,int y)   2 {   3     int Sum=0;   4     for(int i=x;i>0;i-=(i&(-i))) {   5         for(int j=y;j>0;j-=(j&(-j))) {   6             Sum+=c[i][j];   7         }   8     }   9     return Sum;  10 }  11   12 void add(int x,int y,int d)  13 {  14     for(int i=x;i<=n;i+=(i&(-i))) {  15         for(int j=y;j<=n;j+=(j&(-j))) {  16             c[i][j]+=d;  17         }  18     }  19 }
View Code

 通过考试考挂的教训,我就在这重推,二维改段求段。A是差分意义下。

sum(x,y)=Sigma(i<=x)Sigma(j<=y)(A[i][i]*(x-(i-1))*(y-(j-1)))

        =Sigma(i<=x)Sigma(j<=y)(A[i][j]*x*y-A[i][j]*x*(j-1)-A[i][j]*y*(i-1)+A[i][j]*x*y);

1 void add(int x,int y,int v_1,int v_2,int v_3,int v_4){ 2     for (int i=x;i<=n;i+=lowbit(i)) 3         for (int j=y;j<=m;j+=lowbit(j)) t_1[i][j]+=v_1,t_2[i][j]+=v_2,t_3[i][j]+=v_3,t_4[i][j]+=v_4; 4 }  5 int sum(int x,int y){ 6     int Sum1=0,Sum2=0,Sum3=0,Sum4=0; 7     for (int i=x;i>0;i-=lowbit(i)) 8         for (int j=y;j>0;j-=lowbit(j)) Sum1+=t_1[i][j],Sum2+=t_2[i][j],Sum3+=t_3[i][j],Sum4+=t_4[i][j]; 9     return Sum1*x*y-Sum2*x-Sum3*y+Sum4;10 }
View Code

  修改操作:

add(a,b,v,v*(b-1),v*(a-1),v*(a-1)*(b-1)); add(a,d+1,-v,(-v)*d,(-v)*(a-1),(-v)*d*(a-1));add(c+1,b,-v,(-v)*(b-1),(-v)*c,(-v)*c*(b-1));add(c+1,d+1,v,v*d,v*c,v*d*c);

  求和操作:

sum(c,d)-sum(a-1,d)-sum(c,b-1)+sum(a-1,b-1)

 均摊logn的清零。

struct Bit{int ts,b[SZ],t[SZ]; void clr() {++ts;}Bit() {ts=0; memset(t,0,sizeof t);}void edt(int x,int y){    for(;x<=n;x+=x&-x)    {
if(t[x]!=ts) t[x]=ts,b[x]=0; (b[x]+=y)%=MOD;}}int sum(int x){ int s=0; for(;x>=1;x-=x&-x) {
if(t[x]!=ts) t[x]=ts,b[x]=0; (s+=b[x])%=MOD;} return s;}}ba,bb;

 

转载于:https://www.cnblogs.com/SXia/p/6784652.html

你可能感兴趣的文章
mysqld_safe A mysqld process already exists
查看>>
六年测试之精华分享:产品质量应从哪些方面提高
查看>>
文件处理
查看>>
for循环
查看>>
【转】Android手机客户端关于二维码扫描的源码--不错
查看>>
【转】Java 多线程(四) 多线程访问成员变量与局部变量
查看>>
【转】gcc warning: braces around scalar initializer (标量初始化的括号)
查看>>
C/C++内存泄漏及检测(vs2005平台)【转】
查看>>
SpringBoot中遇到的问题---【Whitelabel Error Page 404 spring boot解决方法】
查看>>
python之路--模块--景丽洋
查看>>
postfix队列管理
查看>>
编译安装nginx
查看>>
操作系统的硬件环境
查看>>
js三种定义类的方法
查看>>
LeetCode——Unique Binary Search Trees
查看>>
Python运算符及基本数据类型
查看>>
noip2006提高组题解
查看>>
最短路(数据处理):HDU 5817 Ice Walls
查看>>
sass揭秘之@mixin,%,@function scss基本使用及操作函数
查看>>
自定义UITabbarController控制器
查看>>