树状数组改段求段
如何运用树状数组进行区间操作
先定义两个树状数组 X, Y
现在我们需要对一个数组 int a[N]; 进行区间操作:[L, R] += val 即 for i:L to R a[i] += val;
再定义一个 int size = R-L+1 , 即区间长度
对应的修改是
1、X[L] += val; X[R+1] -= val;
2、Y[L] += -1 * val * (L-1); Y[R+1] += val * R;
对应的查询是
当我们求和 时在树状数组中操作是 ans = X.sum(k) * k + Y.sum(k)
分类讨论一下k分别在 [1,L-1] , [L, R] , [R+1, +]
1、k[1,L-1]
显然 X.sum(k) == 0 且 Y.sum(k) == 0 -> ans = X.sum(k)*k + Y.sum(k) = 0*i+0 = 0 结果与实际相符。
2、k[L, R]
X.sum(k) * k = X[L] * k = val * k, Y.sum(k) = Y[L] = -1 * val * (L-1)
ans = val * k - val * (L-1) = val * ( k - (L-1) );
3、k[R+1,
]
X.sum(k) * k = ( x[L] + x[R] ) * k = 0 * k = 0;
Y.sum(k) = Y[L] + Y[R] = -val * (L-1) + val * R = val * (R-L+1) = val * size
X.sum(k) * k + Y.sum(k) = val * size
证毕
以下模版中两个树状数组c[0], c[1] 对应上述的X, Y
区间修改:add(L, R, val)
求 int a[N]的前缀和 get_pre(R)
区间查询:get(L,R)
#define inline __inline__ __attribute__((always_inline)) namespace pb_ds{ const int N=100001; typedef long long ll; int n; template<class T> struct BIT_tree{ T c[2][N]; inline int lowbit(int x){ return x&(-x); } inline T sum(T *b,int x){ T ans=0; if(!x)ans=b[0]; for(;x;x-=lowbit(x))ans+=b[x]; return ans; } inline void add(T *b,int x,T val){ if(!x)b[x]+=val,x++; for(;x<=n;x+=lowbit(x))b[x]+=val; } inline T get_pre(int r){ return sum(c[0],r)*r+sum(c[1],r); } inline modify(int l,int r,T val){ add(c[0],l,val); add(c[0],r+1,-val); add(c[1],l,val*(1-l)); add(c[1],r+1,val*r); } inline T inquiry(int l,int r){ return get_pre(r)-get_pre(l-1); } }; BIT_tree<ll>bt; }; int main(){ }
转载自:http://blog.csdn.net/qq574857122/article/details/46876877