树状数组(Binary Index Tree)
一维BIT(单点更新,区间求和):
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring> using namespace std; const int N = ;
typedef long long LL;
inline int lowbit(int x) { return x & -x;}
struct BIT {
LL s[N], sz;
void init(int n) { sz = n; for (int i = ; i <= n; i++) s[i] = ;}
void add(int x, LL v) { for (x <= ? : x; x <= sz; x += lowbit(x)) s[x] += v;}
LL sum(int x) { LL r = ; for ( ; x > ; x -= lowbit(x)) r += s[x]; return r;}
LL sum(int x, int y) { return sum(y) - sum(x - );}
} bit; int main() {
//freopen("in", "r", stdin);
int n, m, T;
scanf("%d", &T);
for (int cas = ; cas <= T; cas++) {
scanf("%d", &n);
bit.init(n);
int x, y;
char op[];
for (int i = ; i <= n; i++) {
scanf("%d", &x);
bit.add(i, x);
}
printf("Case %d:\n", cas);
while (~scanf("%s", op) && op[] != 'E') {
scanf("%d%d", &x, &y);
if (op[] == 'A') bit.add(x, y);
if (op[] == 'S') bit.add(x, -y);
if (op[] == 'Q') printf("%lld\n", bit.sum(x, y));
}
}
return ;
}
一维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
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring> using namespace std; const int N = ;
typedef long long LL;
inline int lowbit(int x) { return x & -x;}
struct BIT {
LL s[N], sz;
void init(int n) { sz = n; for (int i = ; i <= n; i++) s[i] = ;}
void add(int x, LL v) { for (x <= ? : x; x <= sz; x += lowbit(x)) s[x] += v;}
LL sum(int x) { LL r = ; for ( ; x > ; x -= lowbit(x)) r += s[x]; return r;}
} ; struct BIT2 {
BIT a, b;
void init(int n) { a.init(n), b.init(n);}
void add(int x, LL d) { a.add(x, d), b.add(x, x * d);}
void add(int x, int y, LL d) { add(x, d), add(y + , -d);}
LL sum(int x) { return (x + ) * a.sum(x) - b.sum(x);}
LL sum(int x, int y) { return sum(y) - sum(x - );}
} bit; int main() {
//freopen("in", "r", stdin);
int n, m;
while (~scanf("%d%d", &n, &m)) {
bit.init(n);
int x, y, z;
char op[];
for (int i = ; i <= n; i++) {
scanf("%d", &x);
bit.add(i, i, x);
}
while (m--) {
scanf("%s", op);
if (op[] == 'Q') {
scanf("%d%d", &x, &y);
printf("%lld\n", bit.sum(x, y));
}
if (op[] == 'C') {
scanf("%d%d%d", &x, &y, &z);
bit.add(x, y, z);
}
}
}
return ;
}
二维BIT(子矩阵修改,单点查询):
简单容斥一下,
add(a,b,c,d)=add(c,d)^add(c,b-1)^add(a-1,d)^add(a-1,b-1)
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio> using namespace std; const int N = ;
inline int lowbit(int x) { return x & -x;}
struct BIT2D {
bool s[N][N];
int sz;
void init(int n) {
sz = n;
for (int i = ; i <= n; i++) for (int j = ; j <= n; j++) s[i][j] = ;
}
void add(int x, int y) {
int t = y;
for ( ; x > ; x -= lowbit(x)) {
for (y = t; y > ; y -= lowbit(y)) {
s[x][y] ^= ;
}
}
}
void add(int a, int b, int c, int d) {
if (a > c) swap(a, c);
if (b > d) swap(b, d);
add(c, d), add(c, b - ), add(a - , d), add(a - , b - );
}
bool sum(int x, int y) {
int t = y;
bool ret = ;
for (x > ? x : ; x <= sz; x += lowbit(x)) {
for (y = t > ? t : ; y <= sz; y += lowbit(y)) {
ret ^= s[x][y];
}
}
return ret;
}
} bit; int main() {
//freopen("in", "r", stdin);
int T, n, m;
scanf("%d", &T);
while (T--) {
scanf("%d%d", &n, &m);
bit.init(n);
char op[];
int a, b, c, d;
while (m--) {
scanf("%s", op);
if (op[] == 'C') {
scanf("%d%d%d%d", &a, &b, &c, &d);
bit.add(a, b, c, d);
}
if (op[] == 'Q') {
scanf("%d%d", &a, &b);
printf("%d\n", bit.sum(a, b));
}
}
if (T) puts("");
}
}
二维BIT(单点更新,子矩阵查询):
类似上一题,
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio> using namespace std; const int N = ;
inline int lowbit(int x) { return x & -x;}
struct BIT2D {
int s[N][N];
int sz;
void init(int n) {
sz = n;
for (int i = ; i <= n; i++) for (int j = ; j <= n; j++) s[i][j] = ;
}
void add(int x, int y, int d) {
int t = y;
for (x = x > ? x : ; x <= sz; x += lowbit(x)) {
for (y = t > ? t : ; y <= sz; y += lowbit(y)) {
s[x][y] += d;
}
}
}
int sum(int x, int y) {
int t = y;
int ret = ;
for (; x > ; x -= lowbit(x)) {
for (y = t; y > ; y -= lowbit(y)) {
ret += s[x][y];
}
}
return ret;
}
int sum(int a, int b, int c, int d) {
if (a > c) swap(a, c);
if (b > d) swap(b, d);
return sum(c, d) - sum(c, b - ) - sum(a - , d) + sum(a - , b - );
}
} bit; int main() {
//freopen("in", "r", stdin);
int op, n;
while (~scanf("%d", &op)) {
while (op != ) {
if (op == ) {
scanf("%d", &n);
bit.init(n);
}
int a, b, c, d;
if (op == ) {
scanf("%d%d%d", &a, &b, &c);
a++, b++;
bit.add(a, b, c);
}
if (op == ) {
scanf("%d%d%d%d", &a, &b, &c, &d);
a++, b++, c++, d++;
printf("%d\n", bit.sum(a, b, c, d));
}
scanf("%d", &op);
}
}
return ;
}
二维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}。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring> using namespace std; const int N = ;
typedef int LL;
inline int lowbit(int x) { return x & -x;}
struct BIT {
LL s[N][N];
int n, m;
void init(int s1, int s2) {
n = s1, m = s2;
for (int i = ; i <= n; i++) for (int j = ; j <= m; j++) s[i][j] = ;
}
void add(int x, int y, int d) {
int t = y > ? y : ;
for (x = x > ? x : ; x <= n; x += lowbit(x)) {
for (y = t; y <= m; y += lowbit(y)) {
s[x][y] += d;
}
}
}
LL sum(int x, int y) {
LL ret = ;
int t = y > ? y : ;
for ( ; x > ; x -= lowbit(x)) {
for (y = t; y > ; y -= lowbit(y)) {
ret += s[x][y];
}
}
return ret;
}
} ; struct BIT2 {
BIT A, B, C, D;
void init(int n, int m) { A.init(n, m), B.init(n, m), C.init(n, m), D.init(n, m);}
void add(int x, int y, LL k) { // add (x,y)-(n,m)
A.add(x, y, k), B.add(x, y, k * x), C.add(x, y, k * y), D.add(x, y, k * x * y);
}
void add(int a, int b, int c, int d, int k) {
if (a > c) swap(a, c);
if (b > d) swap(b, d);
add(a, b, k), add(a, d + , -k), add(c + , b, -k), add(c + , d + , k);
}
LL sum(int x, int y) { // sum (1,1)-(x,y)
return (x + ) * (y + ) * A.sum(x, y) - (y + ) * B.sum(x, y) - (x + ) * C.sum(x, y) + D.sum(x, y);
}
LL sum(int a, int b, int c, int d) {
if (a > c) swap(a, c);
if (b > d) swap(b, d);
return sum(c, d) - sum(c, b - ) - sum(a - , d) + sum(a - , b - );
}
} bit; int main() {
//freopen("in", "r", stdin);
char op[];
int a, b, c, d, e;
while (~scanf("%s", op)) {
if (op[] == 'X') {
scanf("%d%d", &a, &b);
bit.init(a, b);
}
if (op[] == 'L') {
scanf("%d%d%d%d%d", &a, &b, &c, &d, &e);
bit.add(a, b, c, d, e);
}
if (op[] == 'k') {
scanf("%d%d%d%d", &a, &b, &c, &d);
printf("%d\n", bit.sum(a, b, c, d));
}
}
return ;
}
二维BIT(子矩阵更新,子矩阵查询):
就是为了做这题,把一维和二维的BIT都做了一遍,原理同上题。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring> using namespace std; const int N = ;
typedef long long LL;
inline int lowbit(int x) { return x & -x;}
struct BIT {
LL s[N][N];
int n, m;
void init(int s1, int s2) {
n = s1, m = s2;
for (int i = ; i <= n; i++) for (int j = ; j <= m; j++) s[i][j] = ;
}
void add(int x, int y, LL d) {
int t = y > ? y : ;
for (x = x > ? x : ; x <= n; x += lowbit(x)) {
for (y = t; y <= m; y += lowbit(y)) {
s[x][y] ^= d;
}
}
}
LL sum(int x, int y) {
LL ret = ;
int t = y > ? y : ;
for ( ; x > ; x -= lowbit(x)) {
for (y = t; y > ; y -= lowbit(y)) {
ret ^= s[x][y];
}
}
return ret;
}
} ; struct BIT2 {
BIT A, B, C, D;
void init(int n, int m) { A.init(n, m), B.init(n, m), C.init(n, m), D.init(n, m);}
void add(int x, int y, LL k) { // add (x,y)-(n,m)
A.add(x, y, k);
//cout << x << ' ' << y << ' ' << k << "??" << endl;
if (x & ) B.add(x, y, k);
if (y & ) C.add(x, y, k);
if (x & y & ) D.add(x, y, k);
}
void add(int a, int b, int c, int d, LL k) {
if (a > c) swap(a, c);
if (b > d) swap(b, d);
add(a, b, k), add(a, d + , k), add(c + , b, k), add(c + , d + , k);
}
LL sum(int x, int y) { // sum (1,1)-(x,y)
LL ret = D.sum(x, y);
if ((x ^ ) & (y ^ ) & ) ret ^= A.sum(x, y);
if ((y ^ ) & ) ret ^= B.sum(x, y);
if ((x ^ ) & ) ret ^= C.sum(x, y);
return ret;
}
LL sum(int a, int b, int c, int d) {
if (a > c) swap(a, c);
if (b > d) swap(b, d);
return sum(c, d) ^ sum(c, b - ) ^ sum(a - , d) ^ sum(a - , b - );
}
} bit; int main() {
//freopen("in", "r", stdin);
int n, m, op;
int a, b, c, d;
LL e;
scanf("%d%d", &n, &m);
bit.init(n, n);
while (m--) {
scanf("%d", &op);
if (op == ) {
scanf("%d%d%d%d", &a, &b, &c, &d);
printf("%d\n", bit.sum(a, b, c, d));
}
if (op == ) {
scanf("%d%d%d%d%lld", &a, &b, &c, &d, &e);
//cout << a << ' ' << b << ' ' << c << ' ' << d << ' ' << e << endl;
bit.add(a, b, c, d, e);
}
}
return ;
}
二维BIT(单点更新,子矩阵查询):
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring> using namespace std; const int N = ;
inline int lowbit(int x) { return x & -x;}
struct BIT {
int s[N][N], n;
void init(int sz) {
n = sz;
for (int i = ; i <= n; i++) for (int j = ; j <= n; j++) s[i][j] = ;
}
void add(int x, int y, int d) {
int t = y > ? y : ;
for (x = x > ? x : ; x <= n; x += lowbit(x)) {
for (y = t; y <= n; y += lowbit(y)) {
s[x][y] += d;
}
}
}
int sum(int x, int y) {
int t = y, ret = ;
for ( ; x > ; x -= lowbit(x)) {
for (y = t; y > ; y -= lowbit(y)) {
ret += s[x][y];
}
}
return ret;
}
int sum(int a, int b, int c, int d) {
if (a > c) swap(a, c);
if (b > d) swap(b, d);
return sum(c, d) - sum(c, b - ) - sum(a - , d) + sum(a - , b - );
}
int get(int x, int y) {
return sum(x, y, x, y);
}
} bit; int main() {
//freopen("in", "r", stdin);
int T, n;
scanf("%d", &T);
for (int cas = ; cas <= T; cas++) {
bit.init();
printf("Case %d:\n", cas);
int a, b, c, d, e;
char s[];
scanf("%d", &n);
while (n--) {
scanf("%s", s);
if (s[] == 'S') {
scanf("%d%d%d%d", &a, &b, &c, &d);
a++, b++, c++, d++;
if (a > c) swap(a, c);
if (b > d) swap(b, d);
printf("%d\n", bit.sum(a, b, c, d) + (c - a + ) * (d - b + ));
}
if (s[] == 'A') {
scanf("%d%d%d", &a, &b, &c);
a++, b++;
bit.add(a, b, c);
}
if (s[] == 'D') {
scanf("%d%d%d", &a, &b, &c);
a++, b++;
c = min(c, bit.get(a, b) + );
bit.add(a, b, -c);
}
if (s[] == 'M') {
scanf("%d%d%d%d%d", &a, &b, &c, &d, &e);
a++, b++, c++, d++;
e = min(e, bit.get(a, b) + );
bit.add(a, b, -e);
bit.add(c, d, e);
}
}
}
return ;
}
——written by Lyon
树状数组(Binary Index Tree)的更多相关文章
- 树状数组 Binary Indexed Tree/Fenwick Tree
2018-03-25 17:29:29 树状数组是一个比较小众的数据结构,主要应用领域是快速的对mutable array进行区间求和. 对于一般的一维情况下的区间和问题,一般有以下两种解法: 1)D ...
- 树状数组(Binary Indexed Tree) 总结
1.“树状数组”数据结构的一种应用 对含有n个元素的数组(a[1],...,a[k],...,a[n]): (1)求出第i个到第j个元素的和,sum=a[i]+...+a[j]. 进行j-i+1次加法 ...
- 树状数组(Binary Indexed Tree(BIT))
先不说别的,这个博客为我学习树状数组提供了很大帮助,奉上传送门 http://blog.csdn.net/int64ago/article/details/7429868 然后就说几个常用的操作 in ...
- 树状数组,Fenwick Tree
Fenwick Tree, (also known as Binary Indexed Tree,二叉索引树), is a high-performance data structure to cal ...
- 树状数组(fenwick tree)
树状数组又称芬威克树,概念上是树状,实际上是使用数组实现的,表现为一种隐式数据结构,balabala...详情请见:https://en.wikipedia.org/wiki/Fenwick_tree ...
- 树形DP+DFS序+树状数组 HDOJ 5293 Tree chain problem(树链问题)
题目链接 题意: 有n个点的一棵树.其中树上有m条已知的链,每条链有一个权值.从中选出任意个不相交的链使得链的权值和最大. 思路: 树形DP.设dp[i]表示i的子树下的最优权值和,sum[i]表示不 ...
- HDU 3436--Queue-jumpers (树状数组 or Splay Tree)
树状数组这个真心想了好久,还是没想出来 %%% www.cppblog.com/Yuan/archive/2010/08/18/123871.html 树状数组求前缀和大于等于k的最大值,第一次看到这 ...
- HDU1166 敌兵布阵 BZOJ1012 最大数[树状数组]
一.前置知识-树状数组 树状数组(binary indexed tree)是一种简洁的代码量很小的数据结构,能够高效的处理前缀区间上的问题.在很多情况下能写树状数组解决的就不用码半天线段树了. 树状数 ...
- NYOJ 108 士兵杀敌1(树状数组)
首先,要先讲讲树状数组: 树状数组(Binary Indexed Tree(BIT), Fenwick Tree)是一个查询和修改复杂度都为log(n)的数据结构.主要用于查询任意两位之间的所有元素之 ...
随机推荐
- 读书笔记--Head First 面向对象分析与设计 目录
1.良好应用程序的基石 2.收集需求 3.需求变更 4.分析 5.良好的设计=灵活的软件 6.解决大问题 7.架构 8.设计原则 9.迭代与测试 10.OOA&D 的生命周期 附录1 附录2
- Twitter web information
http://developer.51cto.com/art/201307/404612.htm 150M active users 300K Qps (read, only 6000 write/s ...
- 解释器模式(Interpreter、Context、Expression)
(给定一门语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子.) 解释器模式的定义是一种按照规定语法进行解析的方案,在现在项目中使用的比较少,其定义如下: Given ...
- Leetcode46. Permutations全排列
给定一个没有重复数字的序列,返回其所有可能的全排列. 示例: 输入: [1,2,3] 输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1 ...
- php pdo操作数据库的方法
PDO 安装 你可以通过 PHP 的 phpinfo() 函数来查看是否安装了PDO扩展. 1.在 Unix /linux系统上安装 PDO 在Unix上或Linux上你需要添加以下扩展: exten ...
- javaScript中的事件对象event是怎样
事件对象event,每当一个事件被触发的时候,就会随之产恒一个事件对象event,该对象中主要包含了关于该事件的基本属性,事件类型type(click.dbclick等值).目标元素target(我的 ...
- 阿里云DMS发布数据库网关服务: 打通网络限制 开启数据库统一管理的万能钥匙
概述 阿里云数据管理DMS在云端可提供专业的数据库服务,除对标本地数据库软件的基础功能外,还包含性能诊断.数据追踪.跨实例SQL查询(含异构数据库类型之间)等专业性功能,同时提供审计安全和企业级数据库 ...
- 2018 8.8 提高A组模拟赛
T1 Description 被污染的灰灰草原上有羊和狼.有N只动物围成一圈,每只动物是羊或狼. 该游戏从其中的一只动物开始,报出[1,K]区间的整数,若上一只动物报出的数是x,下一只动物可以报[x+ ...
- Django 点滴
1.views 中可用 render 传递参数 def home(request): info_dict = {'site': u'震撼学习', 'content': u'各种IT技术'} #Tuto ...
- Katalon系列十八:用例变量&用例间调用
一.用例变量写用例时,我们可以用代码定义变量,如:String name = '新闻'println(name) 上面是硬编码,我们也可以在用例里定义变量,只在该用例里生效哦,想跨用例就用全局变量. ...