概述
数据结构介绍
线段树(Segment Tree)
树状数组,即二叉索引树(Binary Index Tree)
典型例题
HDU1166敌兵布阵
这题只涉及到单点修改,关于区间修改:【洛谷模板题】 线段树、树状数组入门(2)
线段树解法
#include <iostream>
using namespace std;
#define LEFT(x) (x << 1)
#define RIGHT(x) ((x << 1) | 1)
int seg[50005 * 4]; //4倍防越界
void pushUp(int a) //由2个子树更新root
{
seg[a] = seg[LEFT(a)] + seg[RIGHT(a)];
}
void build(int root, int low, int high)
{
if(low == high)
{
cin >> seg[root]; //输入
return;
}
int mid = (low + high) / 2;
build(LEFT(root), low, mid); //递归建树
build(RIGHT(root), mid + 1, high);
pushUp(root);
}
void update(int root, int low, int high, int pos, int add) //若区间包含了单点,则更新
{
seg[root] += add;
if(low == high) return;
int mid = (low + high) / 2;
if(pos <= mid)
update(LEFT(root), low, mid, pos, add);
else
update(RIGHT(root), mid + 1, high, pos, add);
}
int getSum(int root, int low, int high, int l, int h)
{
if(l <= low && high <= h) //当前区间[low,high]被包含在查询区间[l,r]内部
return seg[root];
int res = 0;
int mid = (low + high) / 2;
if(l <= mid) //区间左边与[l,h]有交集
res += getSum(LEFT(root), low, mid, l, h);
if(h > mid)
res += getSum(RIGHT(root), mid + 1, high, l, h);
return res;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t, n, a, b;
string op;
cin >> t;
for(int i = 1; i <= t; ++i)
{
cout << "Case " << i << ":n";
cin >> n;
build(1, 1, n);
while(cin >> op && op != "End")
{
cin >> a >> b;
if(op == "Query")
cout << getSum(1, 1, n, a, b) << 'n';
else if(op == "Add")
update(1, 1, n, a, b);
else update(1, 1, n, a, -b);
}
}
return 0;
}
树状数组解法
#include <iostream>
#include <cstring>
using namespace std;
#define lowbit(x) ((x)&(-x))
int t, n, tmp, a, b;
string op;
int c[50005]; //c[i]保存了Σ([i-lowbit(i)+1,i])
void update(int x, int add) //x+lowbit(x)即为其父节点
{
while(x <= n)
{
c[x] += add;
x += lowbit(x);
}
}
int getSum(int x) //如求1~6,此时x=6
{
int res = 0; //(110) = (10) + (100)
while(x)
{
res += c[x];
x -= lowbit(x);
}
return res;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> t;
for(int i = 1; i <= t; ++i)
{
cout << "Case " << i << ":n";
cin >> n;
memset(c, 0, sizeof(c));
for(int i = 1; i <= n; ++i)
{
cin >> tmp;
update(i, tmp);
}
while(cin >> op && op != "End")
{
cin >> a >> b;
if(op == "Query")
cout << getSum(b) - getSum(a - 1) << 'n';
else if(op == "Add")
update(a, b);
else update(a, -b);
}
}
return 0;
}
最后
以上就是自由蜻蜓为你收集整理的【HDU1166 敌兵布阵】 线段树、树状数组入门(1)的全部内容,希望文章能够帮你解决【HDU1166 敌兵布阵】 线段树、树状数组入门(1)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复