树状数组(Binary Index Tree)
一维BIT(单点更新,区间求和):
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <cstring> 5 6 using namespace std; 7 8 const int N = 111111; 9 typedef long long LL; 10 inline int lowbit(int x) { return x & -x;} 11 struct BIT { 12 LL s[N], sz; 13 void init(int n) { sz = n; for (int i = 1; i <= n; i++) s[i] = 0;} 14 void add(int x, LL v) { for (x <= 0 ? 1 : x; x <= sz; x += lowbit(x)) s[x] += v;} 15 LL sum(int x) { LL r = 0; for ( ; x > 0; x -= lowbit(x)) r += s[x]; return r;} 16 LL sum(int x, int y) { return sum(y) - sum(x - 1);} 17 } bit; 18 19 int main() { 20 //freopen("in", "r", stdin); 21 int n, m, T; 22 scanf("%d", &T); 23 for (int cas = 1; cas <= T; cas++) { 24 scanf("%d", &n); 25 bit.init(n); 26 int x, y; 27 char op[10]; 28 for (int i = 1; i <= n; i++) { 29 scanf("%d", &x); 30 bit.add(i, x); 31 } 32 printf("Case %d:\n", cas); 33 while (~scanf("%s", op) && op[0] != 'E') { 34 scanf("%d%d", &x, &y); 35 if (op[0] == 'A') bit.add(x, y); 36 if (op[0] == 'S') bit.add(x, -y); 37 if (op[0] == 'Q') printf("%lld\n", bit.sum(x, y)); 38 } 39 } 40 return 0; 41 }
一维BIT(区间求和,区间更新):
d[i]=a[i]-a[i-1](查分数组)
sigma{a[i]}=(n+1)*sigma{d[i]}-sigma{d[i]*i}
3468 -- A Simple Problem with Integers
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <cstring> 5 6 using namespace std; 7 8 const int N = 111111; 9 typedef long long LL; 10 inline int lowbit(int x) { return x & -x;} 11 struct BIT { 12 LL s[N], sz; 13 void init(int n) { sz = n; for (int i = 1; i <= n; i++) s[i] = 0;} 14 void add(int x, LL v) { for (x <= 0 ? 1 : x; x <= sz; x += lowbit(x)) s[x] += v;} 15 LL sum(int x) { LL r = 0; for ( ; x > 0; x -= lowbit(x)) r += s[x]; return r;} 16 } ; 17 18 struct BIT2 { 19 BIT a, b; 20 void init(int n) { a.init(n), b.init(n);} 21 void add(int x, LL d) { a.add(x, d), b.add(x, x * d);} 22 void add(int x, int y, LL d) { add(x, d), add(y + 1, -d);} 23 LL sum(int x) { return (x + 1) * a.sum(x) - b.sum(x);} 24 LL sum(int x, int y) { return sum(y) - sum(x - 1);} 25 } bit; 26 27 int main() { 28 //freopen("in", "r", stdin); 29 int n, m; 30 while (~scanf("%d%d", &n, &m)) { 31 bit.init(n); 32 int x, y, z; 33 char op[3]; 34 for (int i = 1; i <= n; i++) { 35 scanf("%d", &x); 36 bit.add(i, i, x); 37 } 38 while (m--) { 39 scanf("%s", op); 40 if (op[0] == 'Q') { 41 scanf("%d%d", &x, &y); 42 printf("%lld\n", bit.sum(x, y)); 43 } 44 if (op[0] == 'C') { 45 scanf("%d%d%d", &x, &y, &z); 46 bit.add(x, y, z); 47 } 48 } 49 } 50 return 0; 51 }
二维BIT(子矩阵修改,单点查询):
简单容斥一下,
add(a,b,c,d)=add(c,d)^add(c,b-1)^add(a-1,d)^add(a-1,b-1)
1 #include <iostream> 2 #include <algorithm> 3 #include <cstring> 4 #include <cstdio> 5 6 using namespace std; 7 8 const int N = 1111; 9 inline int lowbit(int x) { return x & -x;} 10 struct BIT2D { 11 bool s[N][N]; 12 int sz; 13 void init(int n) { 14 sz = n; 15 for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) s[i][j] = 0; 16 } 17 void add(int x, int y) { 18 int t = y; 19 for ( ; x > 0; x -= lowbit(x)) { 20 for (y = t; y > 0; y -= lowbit(y)) { 21 s[x][y] ^= 1; 22 } 23 } 24 } 25 void add(int a, int b, int c, int d) { 26 if (a > c) swap(a, c); 27 if (b > d) swap(b, d); 28 add(c, d), add(c, b - 1), add(a - 1, d), add(a - 1, b - 1); 29 } 30 bool sum(int x, int y) { 31 int t = y; 32 bool ret = 0; 33 for (x > 0 ? x : 1; x <= sz; x += lowbit(x)) { 34 for (y = t > 0 ? t : 1; y <= sz; y += lowbit(y)) { 35 ret ^= s[x][y]; 36 } 37 } 38 return ret; 39 } 40 } bit; 41 42 int main() { 43 //freopen("in", "r", stdin); 44 int T, n, m; 45 scanf("%d", &T); 46 while (T--) { 47 scanf("%d%d", &n, &m); 48 bit.init(n); 49 char op[3]; 50 int a, b, c, d; 51 while (m--) { 52 scanf("%s", op); 53 if (op[0] == 'C') { 54 scanf("%d%d%d%d", &a, &b, &c, &d); 55 bit.add(a, b, c, d); 56 } 57 if (op[0] == 'Q') { 58 scanf("%d%d", &a, &b); 59 printf("%d\n", bit.sum(a, b)); 60 } 61 } 62 if (T) puts(""); 63 } 64 }
二维BIT(单点更新,子矩阵查询):
类似上一题,
1 #include <iostream> 2 #include <algorithm> 3 #include <cstring> 4 #include <cstdio> 5 6 using namespace std; 7 8 const int N = 1111; 9 inline int lowbit(int x) { return x & -x;} 10 struct BIT2D { 11 int s[N][N]; 12 int sz; 13 void init(int n) { 14 sz = n; 15 for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) s[i][j] = 0; 16 } 17 void add(int x, int y, int d) { 18 int t = y; 19 for (x = x > 0 ? x : 1; x <= sz; x += lowbit(x)) { 20 for (y = t > 0 ? t : 1; y <= sz; y += lowbit(y)) { 21 s[x][y] += d; 22 } 23 } 24 } 25 int sum(int x, int y) { 26 int t = y; 27 int ret = 0; 28 for (; x > 0; x -= lowbit(x)) { 29 for (y = t; y > 0; y -= lowbit(y)) { 30 ret += s[x][y]; 31 } 32 } 33 return ret; 34 } 35 int sum(int a, int b, int c, int d) { 36 if (a > c) swap(a, c); 37 if (b > d) swap(b, d); 38 return sum(c, d) - sum(c, b - 1) - sum(a - 1, d) + sum(a - 1, b - 1); 39 } 40 } bit; 41 42 int main() { 43 //freopen("in", "r", stdin); 44 int op, n; 45 while (~scanf("%d", &op)) { 46 while (op != 3) { 47 if (op == 0) { 48 scanf("%d", &n); 49 bit.init(n); 50 } 51 int a, b, c, d; 52 if (op == 1) { 53 scanf("%d%d%d", &a, &b, &c); 54 a++, b++; 55 bit.add(a, b, c); 56 } 57 if (op == 2) { 58 scanf("%d%d%d%d", &a, &b, &c, &d); 59 a++, b++, c++, d++; 60 printf("%d\n", bit.sum(a, b, c, d)); 61 } 62 scanf("%d", &op); 63 } 64 } 65 return 0; 66 }
二维BIT(子矩阵更新,子矩阵查询):
a[i][j]——(i,j)-(n,m)增量(差分矩阵)
S[i][j]——(1,1)-(i,j)求和
S[x][y]=sigma{a[i][j]*(x-i+1)*(y-j+1)}=sigma{a[i][j]*(x+1)*(y+1)-(y+1)*a[i][j]*i-(x+1)*a[i][j]*j+a[i][j]*i*j}
令A[x][y]=sigma{a[i][j]},B[x][y]=sigma{a[i][j]*i},C[x][y]=sigma{a[i][j]*j},D[x][y]=sigma{a[i][j]*i*j}。
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <cstring> 5 6 using namespace std; 7 8 const int N = 2222; 9 typedef int LL; 10 inline int lowbit(int x) { return x & -x;} 11 struct BIT { 12 LL s[N][N]; 13 int n, m; 14 void init(int s1, int s2) { 15 n = s1, m = s2; 16 for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) s[i][j] = 0; 17 } 18 void add(int x, int y, int d) { 19 int t = y > 0 ? y : 1; 20 for (x = x > 0 ? x : 1; x <= n; x += lowbit(x)) { 21 for (y = t; y <= m; y += lowbit(y)) { 22 s[x][y] += d; 23 } 24 } 25 } 26 LL sum(int x, int y) { 27 LL ret = 0; 28 int t = y > 0 ? y : 1; 29 for ( ; x > 0; x -= lowbit(x)) { 30 for (y = t; y > 0; y -= lowbit(y)) { 31 ret += s[x][y]; 32 } 33 } 34 return ret; 35 } 36 } ; 37 38 struct BIT2 { 39 BIT A, B, C, D; 40 void init(int n, int m) { A.init(n, m), B.init(n, m), C.init(n, m), D.init(n, m);} 41 void add(int x, int y, LL k) { // add (x,y)-(n,m) 42 A.add(x, y, k), B.add(x, y, k * x), C.add(x, y, k * y), D.add(x, y, k * x * y); 43 } 44 void add(int a, int b, int c, int d, int k) { 45 if (a > c) swap(a, c); 46 if (b > d) swap(b, d); 47 add(a, b, k), add(a, d + 1, -k), add(c + 1, b, -k), add(c + 1, d + 1, k); 48 } 49 LL sum(int x, int y) { // sum (1,1)-(x,y) 50 return (x + 1) * (y + 1) * A.sum(x, y) - (y + 1) * B.sum(x, y) - (x + 1) * C.sum(x, y) + D.sum(x, y); 51 } 52 LL sum(int a, int b, int c, int d) { 53 if (a > c) swap(a, c); 54 if (b > d) swap(b, d); 55 return sum(c, d) - sum(c, b - 1) - sum(a - 1, d) + sum(a - 1, b - 1); 56 } 57 } bit; 58 59 int main() { 60 //freopen("in", "r", stdin); 61 char op[2]; 62 int a, b, c, d, e; 63 while (~scanf("%s", op)) { 64 if (op[0] == 'X') { 65 scanf("%d%d", &a, &b); 66 bit.init(a, b); 67 } 68 if (op[0] == 'L') { 69 scanf("%d%d%d%d%d", &a, &b, &c, &d, &e); 70 bit.add(a, b, c, d, e); 71 } 72 if (op[0] == 'k') { 73 scanf("%d%d%d%d", &a, &b, &c, &d); 74 printf("%d\n", bit.sum(a, b, c, d)); 75 } 76 } 77 return 0; 78 }
二维BIT(子矩阵更新,子矩阵查询):
就是为了做这题,把一维和二维的BIT都做了一遍,原理同上题。
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <cstring> 5 6 using namespace std; 7 8 const int N = 1111; 9 typedef long long LL; 10 inline int lowbit(int x) { return x & -x;} 11 struct BIT { 12 LL s[N][N]; 13 int n, m; 14 void init(int s1, int s2) { 15 n = s1, m = s2; 16 for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) s[i][j] = 0; 17 } 18 void add(int x, int y, LL d) { 19 int t = y > 0 ? y : 1; 20 for (x = x > 0 ? x : 1; x <= n; x += lowbit(x)) { 21 for (y = t; y <= m; y += lowbit(y)) { 22 s[x][y] ^= d; 23 } 24 } 25 } 26 LL sum(int x, int y) { 27 LL ret = 0; 28 int t = y > 0 ? y : 1; 29 for ( ; x > 0; x -= lowbit(x)) { 30 for (y = t; y > 0; y -= lowbit(y)) { 31 ret ^= s[x][y]; 32 } 33 } 34 return ret; 35 } 36 } ; 37 38 struct BIT2 { 39 BIT A, B, C, D; 40 void init(int n, int m) { A.init(n, m), B.init(n, m), C.init(n, m), D.init(n, m);} 41 void add(int x, int y, LL k) { // add (x,y)-(n,m) 42 A.add(x, y, k); 43 //cout << x << ' ' << y << ' ' << k << "??" << endl; 44 if (x & 1) B.add(x, y, k); 45 if (y & 1) C.add(x, y, k); 46 if (x & y & 1) D.add(x, y, k); 47 } 48 void add(int a, int b, int c, int d, LL k) { 49 if (a > c) swap(a, c); 50 if (b > d) swap(b, d); 51 add(a, b, k), add(a, d + 1, k), add(c + 1, b, k), add(c + 1, d + 1, k); 52 } 53 LL sum(int x, int y) { // sum (1,1)-(x,y) 54 LL ret = D.sum(x, y); 55 if ((x ^ 1) & (y ^ 1) & 1) ret ^= A.sum(x, y); 56 if ((y ^ 1) & 1) ret ^= B.sum(x, y); 57 if ((x ^ 1) & 1) ret ^= C.sum(x, y); 58 return ret; 59 } 60 LL sum(int a, int b, int c, int d) { 61 if (a > c) swap(a, c); 62 if (b > d) swap(b, d); 63 return sum(c, d) ^ sum(c, b - 1) ^ sum(a - 1, d) ^ sum(a - 1, b - 1); 64 } 65 } bit; 66 67 int main() { 68 //freopen("in", "r", stdin); 69 int n, m, op; 70 int a, b, c, d; 71 LL e; 72 scanf("%d%d", &n, &m); 73 bit.init(n, n); 74 while (m--) { 75 scanf("%d", &op); 76 if (op == 1) { 77 scanf("%d%d%d%d", &a, &b, &c, &d); 78 printf("%d\n", bit.sum(a, b, c, d)); 79 } 80 if (op == 2) { 81 scanf("%d%d%d%d%lld", &a, &b, &c, &d, &e); 82 //cout << a << ' ' << b << ' ' << c << ' ' << d << ' ' << e << endl; 83 bit.add(a, b, c, d, e); 84 } 85 } 86 return 0; 87 }
二维BIT(单点更新,子矩阵查询):
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <cstring> 5 6 using namespace std; 7 8 const int N = 1111; 9 inline int lowbit(int x) { return x & -x;} 10 struct BIT { 11 int s[N][N], n; 12 void init(int sz) { 13 n = sz; 14 for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) s[i][j] = 0; 15 } 16 void add(int x, int y, int d) { 17 int t = y > 0 ? y : 1; 18 for (x = x > 0 ? x : 1; x <= n; x += lowbit(x)) { 19 for (y = t; y <= n; y += lowbit(y)) { 20 s[x][y] += d; 21 } 22 } 23 } 24 int sum(int x, int y) { 25 int t = y, ret = 0; 26 for ( ; x > 0; x -= lowbit(x)) { 27 for (y = t; y > 0; y -= lowbit(y)) { 28 ret += s[x][y]; 29 } 30 } 31 return ret; 32 } 33 int sum(int a, int b, int c, int d) { 34 if (a > c) swap(a, c); 35 if (b > d) swap(b, d); 36 return sum(c, d) - sum(c, b - 1) - sum(a - 1, d) + sum(a - 1, b - 1); 37 } 38 int get(int x, int y) { 39 return sum(x, y, x, y); 40 } 41 } bit; 42 43 int main() { 44 //freopen("in", "r", stdin); 45 int T, n; 46 scanf("%d", &T); 47 for (int cas = 1; cas <= T; cas++) { 48 bit.init(1001); 49 printf("Case %d:\n", cas); 50 int a, b, c, d, e; 51 char s[3]; 52 scanf("%d", &n); 53 while (n--) { 54 scanf("%s", s); 55 if (s[0] == 'S') { 56 scanf("%d%d%d%d", &a, &b, &c, &d); 57 a++, b++, c++, d++; 58 if (a > c) swap(a, c); 59 if (b > d) swap(b, d); 60 printf("%d\n", bit.sum(a, b, c, d) + (c - a + 1) * (d - b + 1)); 61 } 62 if (s[0] == 'A') { 63 scanf("%d%d%d", &a, &b, &c); 64 a++, b++; 65 bit.add(a, b, c); 66 } 67 if (s[0] == 'D') { 68 scanf("%d%d%d", &a, &b, &c); 69 a++, b++; 70 c = min(c, bit.get(a, b) + 1); 71 bit.add(a, b, -c); 72 } 73 if (s[0] == 'M') { 74 scanf("%d%d%d%d%d", &a, &b, &c, &d, &e); 75 a++, b++, c++, d++; 76 e = min(e, bit.get(a, b) + 1); 77 bit.add(a, b, -e); 78 bit.add(c, d, e); 79 } 80 } 81 } 82 return 0; 83 }
——written by Lyon