树状数组(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)的数据结构.主要用于查询任意两位之间的所有元素之 ...
随机推荐
- java多线程三种方式
java多线程都有几种方式 有三种: (1)继承Thread类,重写run函数 创建: class xx extends Thread{ public void run(){ Thread.sleep ...
- 【solr】SolrCloud中索引数据存储于HDFS
SolrCloud中索引数据存储于HDFS 本人最近使用SolrCloud存储索引日志条件,便于快速索引,因为我的索引条件较多,每天日志记录较大,索引想到将日志存入到HDFS中,下面就说说怎么讲sol ...
- CSS min-height 属性
实例 设置段落的最小高度: p { min-height:100px; } 浏览器支持 IE Firefox Chrome Safari Opera 所有主流浏览器都支持 min-height 属性. ...
- 提升mysql服务器性能(索引与查询优化)
原文:提升mysql服务器性能(索引与查询优化) 版权声明:皆为本人原创,复制必究 https://blog.csdn.net/m493096871/article/details/90138407 ...
- 2019.9.24 csp-s模拟测试51(a) 反思总结
T1:还在头铁,顺便复习了一下lct[虽然这题用不上因为复杂度不对] 头铁结束. 虽然题目存在换根的操作,实际上并不用真的换根. 2操作中求lca的时候只要考虑原树上root和x.y的lca以及x,y ...
- WIN7快捷键大全
1. 轻松访问键盘快捷方式 按住右Sht 8秒钟: 启用和关闭筛选键 按左 Alt+左 Sht+PrtScn(或 PrtScn):启用或关闭高对比度 按左 Alt+左 Sht+Num Lock :启用 ...
- 【CodeVS】【2004年NOIP全国联赛提高组】1057 津津的储蓄计划
1057 津津的储蓄计划 2004年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 青铜 Bronze 题目描述 Description 津津的零花钱一直都是 ...
- Python结合OpenCV学习资料
1.sunny2038的专栏 http://blog.csdn.net/sunny2038 作者建立了一个学习系列.讲得非常具体,有非常多的主要的图像处理实例. 2. https://github. ...
- C++之自定义key类型,重载操作符
#include <map>#include <string>using namespace std;class MyString{ public:MyString(){m_s ...
- Apple Watch和Apple Pay将助苹果成为首家市值万亿美元公司
苹果公司周二盘中市值首次突破7000亿美元,成为标普中首家市值超过7000亿美元的公司,市值是第二名Exxon的1.7倍.有分析师预测苹果在明年的市值将会逼近8000亿美元,不过如果参考著名激进投资人 ...