参考:
单点修改,区间查询
#include <bits/stdc++.h>
using namespace std;
/*
树状数组实现单点修改
区间查询
*/
int N;
int tree[100];
int lowbit(int x) {
return x & (-x);
}
void add(int k,int n) {
while (k <= N) {
tree[k] += n;
k += lowbit(k);
}
}
int query(int l,int r) {
int res = 0;
for (int i = l - 1; i; i -= lowbit(i))
res -= tree[i];
for (int i = r; i; i -= lowbit(i))
res += tree[i];
return res;
}
int main() {
cin >> N;
for (int i = 1; i <= N; i++)
{
int num;
cin >> num;
add(i, num);
}
cout << query(1, 3);
}
区间修改,单点查询
#include <bits/stdc++.h>
using namespace std;
/*
树状数组实现单点修改
区间查询
*/
int N;
int a[100];
int tree[100];//储存前缀和数组
int lowbit(int x) {
return x & (-x);
}
void add(int k,int n) {
while (k <= N) {
tree[k] += n;
k += lowbit(k);
}
}
int query(int l,int r) {
int res = 0;
for (int i = l - 1; i; i -= lowbit(i))
res -= tree[i];
for (int i = r; i; i -= lowbit(i))
res += tree[i];
return res;
}
int main() {
cin >> N;
a[0] = 0;
for (int i = 1; i <= N; i++) {
cin >> a[i];
add(i, a[i] - a[i - 1]);
}
//实现区间修改 l r num 1 3 +2
add(1, 2);
add(4, -2);
//实现单点查询 查询1
cout << tree[1];
}
区间修改,区间查询
这一类操作使用树状数组就显得及其复杂,这时候我们建议使用扩展性更强的线段树来解决,在此就不进行树状数组的讲解了.
接下来是我自己的理解:
树状数组是为了解决一些单点修改 区间查询的问题 如果加上差分数组可以用来解决区间修改和单点查询问题 由于编程简单可以用来替代一些线段树的情况 但不是绝对的
难一点的题就是逆序对:
也就是poj-2299
本题的关键是逆序对:i>j a[i]<a[j]为一个逆序对
只能相邻的交换 本题转换为消除所有的逆序对需要多少次 一次只能消除一对 求逆序对总数
利用树状数组实现同时离散化
#include <bits/stdc++.h>
using namespace std;
/*
树状数组实现单点修改
区间查询
*/
struct node {
int value;
int id; // 表示出现顺序 用来表示插入顺序
bool operator<(node& n) const { return value < n.value; }
};
int N;
int Rank[500004];
int tree[500004];
int lowbit(int x) {
return x & (-x);
}
void add(int k, int n) {
while (k <= N) {
tree[k] += n;
k += lowbit(k);
}
}
int query(int l, int r) {
int res = 0;
for (int i = l - 1; i; i -= lowbit(i))
res -= tree[i];
for (int i = r; i; i -= lowbit(i))
res += tree[i];
return res;
}
vector<node> n;
int main() {
while (cin >> N && N != 0) {
n.clear();
n.resize(N + 1);
fill(tree, tree + N + 1, 0); // 重置树状数组
for (int i = 1; i <= N; i++) {
cin >> n[i].value;
n[i].id = i;
}
sort(n.begin() + 1, n.end());
for (int i = 1; i <= N; i++) {
Rank[n[i].id] = i;
}
int ans = 0;
for (int i = 1; i <= N; i++) {
int pos = Rank[i];
ans += query(pos + 1, N); // digit+1~n中有多少数字已经出现就贡献多少逆序对数,累加到答案
add(pos, 1); // 单点修改
}
cout << ans << endl; // 输出结果
}
return 0;
}