您的位置:首页 > 其它

hdu1166线段树

2015-08-11 17:08 295 查看
线段树入门题,线段树除开它的叶子节点其余为区间。

建立线段树的操作可以在wiki上搜索。

这道题有三个操作,query和sub和add

sub和add的使用的函数一样,用update来更新,不同的是

要用sub传值的时候把delta加个负号。

线段树的建树;bulid函数

采用递归的形式来进行建树,只有当为叶子节点才会输入进

数字。但某一分支的叶子节点输入完毕,用了push_up函数

向上更新它们的父节点。

线段树的更新:update函数

跟建树的原理是很相像的,因为更新的时候是叶子节点更新,所以

需要分区间来更新,并且更新了叶子节点后向上更新父节点
#include<iostream>
#include<fstream>
#include<string>
#include<cstring>
using namespace std;
#define lchild rt<<1,l,m
#define rchild rt<<1|1,m+1,r
int N;
#define maxn 50010
int tree[3 * maxn];
void push_up(int rt)
{
tree[rt] = tree[rt << 1] + tree[rt << 1 | 1];
}
void build(int rt = 1, int l = 1, int r = N)
{
if (l == r)
{
cin >> tree[rt];
return;
}
int m = (l + r) >> 1;
build(lchild);
build(rchild);
push_up(rt);
}
void update(int p, int delta, int rt = 1, int l = 1, int r = N)
{
if (l == r)
{
tree[rt] += delta;
return;
}
int m = (l + r) >> 1;
if (p <= m)
update(p, delta, lchild);
else
update(p, delta, rchild);
push_up(rt);
}
int query(int L, int R, int rt = 1, int l = 1, int r = N)
{
if (L <= l&&r <= R)
return tree[rt];
int m = (l + r) >> 1;
int ret = 0;
if (L <= m)
ret += query(L, R, lchild);
if (R > m)
ret += query(L, R, rchild);
return ret;
}
int main()
{
int T;
cin >> T;
for (int i = 1; i <= T; i++)
{
//scanf("%d", &N);
cin >> N;
build();
//string s;
char s[8] = "";
printf("Case %d:\n", i);
while (1)
{
scanf("%s", s);
//getchar();
int f, r;
if (!strcmp(s, "Query"))
{
scanf("%d%d",&f,&r);
cout << query(f, r) << endl;
}
if (!strcmp(s, "Add"))
{
scanf("%d%d",&f,&r);
update(f, r);
}
if (!strcmp(s, "Sub"))
{
scanf("%d%d",&f,&r);
update(f, -r);
}
if (!strcmp(s, "End"))
{
break;
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: