Support interval changes Fenwick tree

Support interval changes Fenwick tree

principle

For an array \ (a \) , and \ (a \) difference \ (C \) , apparently \ (c [i] = a
[i] -a [i-1] \) then for the array a there prefix and
\ (\ sum_ {i = 1 } ^ n {a_i} = c [1] + (c [1] + c [2]) + ... (c [1] + c [2] +. .. + c [n]) \
) further:
\ (\ sum_. 1 = {I} ^ {a_i} = n-C [. 1] + n-C * [2] * (. 1-n-) + ... + c [n] * (n-
n + 1) \) deployed in parenthesis
\ (\ sum_ {i = 1 } ^ n {a_i} = c [1] * n + c [2] * n + ... + c [n] * n- (c [
1] * (1-1) + c [2] * (2-1) + ... + c [n] * (n-1)) \) is the
\ ( \ sum_ {i = 1} ^ n {a_i} = n * \ sum_ {i = 1} ^ n {c [i]} - \ sum_ {i = 1} ^ n {c [i] * (i-1 )} \)
thus maintains a prefix and the need to maintain an array of two differential prefix and \ (c [i] \) and \ ((. 1-I) * C [I] \) , corresponding to the maintenance \ (\ sum_ {i . 1} ^ {n-= C [I]} \) , \ (\ sum_. 1} ^ {n-I = {(I-. 1) * C [I]} \)
As used herein, two arrays of the differential array tree prefix and maintenance, were named as \ (tr \) and\(tr1\)

achieve

First clear the tree basic array of two basic operations: range query and monotonous inquiries . Fenwick tree maintenance and the use of prefixes:

  1. Interval Query \ (\ Query {text} (k) \) , the prefix between 1 and k \ (\ sum_ {i = 1 } ^ k {a [i]} \)
  2. Modifying single point \ (\ the Add {text} (K, X) \) , \ (A [K] + = X \)

Then for this article support section modified dendritic array has the following:
1. Interval Modify \ (\ the Add {text} (L, r, K) \) (L and r inclusive), the operation is equivalent to \ (\ {ADD1 text (L, X)} \) , \ (\ {text} ADD1 (R & lt +. 1, the -X-) \) and \ (\ text {add2} ( l, (l-1) * x) \) , \ (\ {text} ADD2 (R & lt +. 1, R & lt * (- X)) \) (differential properties defined)
2. query interval, \ (querysum (K) \) , the operation is equivalent to \ (k * \ text {query1} (k) * k- \ text {query2} (k) \)

operating

Basic Fenwick tree

To achieve a \ (O (log (n) ) \) single-point range and modify the query.
It supports single modification, the query interval, a single point of inquiry.

int n, m;
ll a[maxn];
ll tr[maxn];  //树状数组1用于维护差分前缀和$\sum_{i=1}^n{c[i]}$
ll tr1[maxn]; //树状数组2用于维护差分前缀和$\sum_{i=1}^n{(i-1)*c[i]}$
int lowbit(int x) { return x & -x; }
void add(ll tr[], int l, ll k) {
  for (int i = l; i <= n; i += lowbit(i)) tr[i] = (tr[i] + k) % mod;
}
ll query(ll tr[], int r) {
  ll res = 0;
  for (int i = r; i; i -= lowbit(i)) res = (res + tr[i]) % mod;
  return res;
}

initialization

void init(int nn) {
  n = nn + 2;//防止空间越界
  for (int i = 0; i <= n; i++) tr[i] = tr1[i] = 0;
}

Interval modification

//[l,r]区间修改+x
void add(int l, int r, int x) {
  add(tr, l, x);
  add(tr, r + 1, -x);
  add(tr1, l, 1ll * (l - 1) * x);
  add(tr1, r + 1, 1ll * r * (-x));
}

Interval inquiry

Query \ (\ sum_ {I}. 1 ^ = KA [I] \) , i.e. the query \ ([, k 1] \ ) prefix and within

//区间查询原数组sum(a[1,k])
ll querysum(int k) {
  return (1ll * query(tr, k) * k)  - query(tr1, k);
}

Interval modification

In \ (a [l] ... a [r] \) interval plus \ (X \) .

//[l,r]区间修改+x
void add(int l, int r, int x) {
  add(tr, l, x);
  add(tr, r + 1, -x);
  add(tr1, l, 1ll * (l - 1) * x);//防止暴int
  add(tr1, r + 1, 1ll * r * (-x));
}

Complexity Analysis

Fenwick tree essence two prefixes and to maintain the differential, wherein the space is three times the interval length, \ (O (n-3 *) \)
time complexity:
the following operations are \ (O (log (n) ) \) :

  • Plus the interval with x
  • Interval inquiry
  • A single point of inquiry
  • Monotonically with x plus

Space complexity compared to segment tree \ (O (4 * n) \) smaller
time complexity same.

Programming complexity almost (They are so hard orz

Integration Templates

Topic Portal

#define judge
// Author: oceanlvr
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
static int faster_iostream = []() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(NULL);
  return 0;
}();
const int maxn = 1e6 + 10;
const int mod = 772002 + 233;
int n, m;
ll a[maxn];
ll tr[maxn];  //树状数组1
ll tr1[maxn]; //树状数组2
int lowbit(int x) { return x & -x; }
void add(ll tr[], int l, ll k) {
  for (int i = l; i <= n; i += lowbit(i)) tr[i] = (tr[i] + k) % mod;
}
ll query(ll tr[], int r) {
  ll res = 0;
  for (int i = r; i; i -= lowbit(i)) res = (res + tr[i]) % mod;
  return res;
}
//[l,r]区间修改+x
void add(int l, int r, int x) {
  add(tr, l, x);
  add(tr, r + 1, -x);
  add(tr1, l, 1ll * (l - 1) * x);
  add(tr1, r + 1, (1ll * r * (-x)%mod+mod)%mod);
}
//区间查询原数组sum(a[1,k])
ll querysum(int k) {
  return (((1ll * query(tr, k) * k) % mod - query(tr1, k) % mod) % mod + mod) %
         mod;
}
void init(int nn) {
  n = nn + 2;
  for (int i = 0; i <= n; i++) tr[i] = tr1[i] = 0;
}
/*------------------------------------------------------------------------------*/
//按题目要求区间[l,r]修改 [l+1,r]+d,[l,l]+a0,[r+1,r+1]-前面两个的和
void addad(int l, int r, int a0, int d) {
  add(l, l, a0);                     //单点l上+a0
  if (l + 1 <= r) add(l + 1, r, d);  //区间[l+1,r] +d
  add(r + 1, r + 1,
      (-(a0 + (1ll * (r - l) * d)) % mod + mod) % mod);  //单点r+1 -前面两个的和
}
//区间查询原数组sum(a[1,k])
int queryad(int k) { return querysum(k); }

int op;
int main() {
#ifndef judge
  freopen("in.txt", "r", stdin);
  freopen("out.txt", "w", stdout);
#endif
  cin >> n >> m;
  for (int i = 1; i <= n; i++) cin >> a[i],a[i]%=mod;
  init(n);
  for (int i = 0; i < m; i++) {
    cin >> op;
    if (op == 1) {
      int x, y;
      cin >> x >> y;
      //(y+1)y/2
      //对[x,x+y-1]加上一个-1
      int l = x, r = min(x + y - 1, n);
      addad(l, r, y, -1);
    } else if (op == 2) {
      int x;
      cin >> x;
      cout << (a[x] + queryad(x)) % mod << endl;
    }
  }

  return 0;
}

Reference links: Fenwick tree plus interval arithmetic sequence

Guess you like

Origin www.cnblogs.com/adameta/p/12406227.html