码迷,mamicode.com
首页 > 编程语言 > 详细

树状数组的区间修改与查询

时间:2018-01-29 22:31:41      阅读:238      评论:0      收藏:0      [点我收藏+]

标签:树状数组   line   树状   return   mat   gpo   inline   ret   sigma   

树状数组的区间修改

我们假设\(a_i\) 为每一个点的本身值,\(d_i = a_i - a_{i-1}\)为差分值。
那么:
\[\sum a_x = \sum_{i=1}^x d_i\]
所以
\[\sum_{i=1}^x a_i = \sum_{i=1}^x \sum_{j=1}^i d_i = \sum_{i=1}^x (x-i+1)d_i\]
把式子拆开得:
\[\sum_{i=1}^x a_i = (x+1)\sum_{i=1}^x d_i - \sum_{i=1}^x i d_i\]
所以用两个树状数组\(c1\),\(c2\)分别维护\(d_i\)\(id_i\)即可。
具体的流程为:

\(Update\):把\([L,R]\)的值全部加上\(val\)
(1)\(Add(c_1, L,val )\)\(Add(c_1 , R+1,-val )\)
(2)\(Add(c_2, L,L*val )\)\(Add(c_2,R+1,-(R+1)*val)\)
._.
\(Get\):查询\([L,R]\)的元素和
(1)$Sigma(x) = (x+1)*Query(c_1,x) - Query(c_2,x) ; $
(2)$Res_{[L,R]} = Sigma(R) - Sigam(L-1) ; $
._.

代码:

IL ll Query(RG int p){
    RG ll d=0 , s=(p+1); 
    while(p)d+= 1ll*s*c1[p]-c2[p], p-=(p&-p); return d;
}
IL int Get(int L,int R){return 1ll*Query(R) - 1ll*Query(L-1);}

IL void Add(ll *bit,int p,int d){while(p<=m)bit[p]+=d,p+=(p&-p);}
IL void Update(RG int L,RG int R,RG int dt){
    Add(c1,L,dt);  Add(c1,R+1,-dt);
    Add(c2,L,dt*L);  Add(c2,R+1,-dt*(R+1));
}

树状数组的区间修改与查询

标签:树状数组   line   树状   return   mat   gpo   inline   ret   sigma   

原文地址:https://www.cnblogs.com/GuessYCB/p/8379498.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!