单点修改,区间查询
关键:lowbit函数 核心代码
int lowbit ( int x)
{
return x & - x;
}
void update ( int x, int c)
{
for ( int i = x; i <= n; i += lowbit ( i) ) tr[ i] += c;
}
ll getsum ( int x)
{
int res = 0 ;
for ( int i = x; i > 0 ; i -= lowbit ( i) ) res += tr[ i] ;
return res;
}
区间修改,区间查询
原理:前缀和, *首先对于一个区间和a[1]+a[2]+…+a[n] 定义c为差分数组, 那么我们可以得到a[1]+a[2]+…+a[n] = (c[1]) + (c[1]+c[2]) + … + (c[1]+c[2]+…+c[n]) 我们进一步将公式转换= nc[1] + (n-1)c[2] +… +c[n] 最终我们得到求和公式= n * (c[1]+c[2]+…+c[n]) - (0 c[1]+1 c[2]+…+(n-1)c[n])
# include <iostream>
# include <algorithm>
# include <cstring>
using namespace std;
typedef long long ll;
const int N = 1e6 + 10 ;
int n, q;
ll a[ N] , c1[ N] , c2[ N] ;
void update ( ll * h, int x, ll y) {
while ( x <= n) {
h[ x] += y;
x += x & - x;
}
}
ll getsum ( ll * h, int x) {
ll res = 0 ;
while ( x) {
res += h[ x] ;
x -= x & - x;
}
return res;
}
int getsum ( int x)
{
int ans = 0 ;
while ( x)
{
ans += c1[ x] ;
x -= lowbit ( x) ;
}
return ans;
}
int main ( int argc, char const * argv[ ] )
{
cin >> n >> q;
for ( int i = 1 ; i <= n; ++ i)
{
cin >> a[ i] ;
update ( c1, i, a[ i] - a[ i - 1 ] ) ;
update ( c2, i, ( i - 1 ) * ( a[ i] - a[ i - 1 ] ) ) ;
}
for ( int i = 1 ; i <= q; i++ ) {
ll id, l, r, x;
cin >> id >> l >> r;
if ( id == 1 ) {
cin >> x;
update ( c1, l, x) ;
update ( c1, r + 1 , - x) ;
update ( c2, l, x * ( l - 1 ) ) ;
update ( c2, r + 1 , - x * r) ;
} else {
ll sum1 = ( l - 1 ) * getsum ( c1, l - 1 ) - getsum ( c2, l - 1 ) ;
ll sum2 = r * getsum ( c1, r) - getsum ( c2, r) ;
cout << sum2 - sum1 << endl;
}
}
return 0 ;
}