hdu1166线段树

来源:互联网 发布:淘宝网店童装图片 编辑:程序博客网 时间:2024/05/18 22:14
线段树入门题,线段树除开它的叶子节点其余为区间。
建立线段树的操作可以在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,rint N;#define maxn 50010int 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;}


0 0
原创粉丝点击