poj 3468 A Simple Problem with Integers
2012-04-05 16:58
260 查看
最近在研究线段树,所以就先找简单点的练练手,虽然简单,但是对于刚入手的我来说,也不简单了,对于大牛就别掺合了,谢谢了。
说说我对线段树的理解吧, 就是定义一个结构体数组, 这个结构体的属性是包含一个线段的始点和终点,以及你所需要的操作属性,比如求一段区间的和,就多定义一个属性和的变量。还有些定义和细节我就不说了。
其次就是建树的过程了,这棵树你可以理解成完全二叉树,但是实质往往不是的。之所以要那么理解是需要它的性质,它的一个结点的左儿子的编号是父节点编号的2倍,右儿子的是2倍+1。再接下来就是你所需要的操作了,查询,更新,求和,删除等。这里讲的是求和。
对于求和,这个不需要输出的操作,我们什么时候更新一段线段的和值呢?又怎么更新呢?起初这个搞得我也很困惑,后来终于搞明白了,更新分两步走的,求和的时候更新一次,另一次就是在查询了,因为时间限制,所以只需要更新所需要的线段就好。对于求和,就是便找线段便更新,假设有一棵树,中间有个你需要找的结点,找到后就依次往上更新其父节点,再父父结点...最后就是根节点啦,对于这个结点的下面就不要更新了,时间问题嘛。
对于查询比求和要简单一点,因为它不需往上更新了,只需跟新到你要找的结点就好,这个便找变更新就好。
说说我对线段树的理解吧, 就是定义一个结构体数组, 这个结构体的属性是包含一个线段的始点和终点,以及你所需要的操作属性,比如求一段区间的和,就多定义一个属性和的变量。还有些定义和细节我就不说了。
其次就是建树的过程了,这棵树你可以理解成完全二叉树,但是实质往往不是的。之所以要那么理解是需要它的性质,它的一个结点的左儿子的编号是父节点编号的2倍,右儿子的是2倍+1。再接下来就是你所需要的操作了,查询,更新,求和,删除等。这里讲的是求和。
对于求和,这个不需要输出的操作,我们什么时候更新一段线段的和值呢?又怎么更新呢?起初这个搞得我也很困惑,后来终于搞明白了,更新分两步走的,求和的时候更新一次,另一次就是在查询了,因为时间限制,所以只需要更新所需要的线段就好。对于求和,就是便找线段便更新,假设有一棵树,中间有个你需要找的结点,找到后就依次往上更新其父节点,再父父结点...最后就是根节点啦,对于这个结点的下面就不要更新了,时间问题嘛。
对于查询比求和要简单一点,因为它不需往上更新了,只需跟新到你要找的结点就好,这个便找变更新就好。
#include<stdio.h> #include<string> #define MAX 100000 struct Node { int l, r; __int64 sum, c; }a[MAX*4]; void built(int l, int r, int step) { a[step].l = l; a[step].r = r; a[step].c = 0; if(l == r) { scanf("%I64d", &a[step].sum); return ; } int mid = (l + r)/2; built(l, mid, step*2); built(mid+1, r, step*2+1); a[step].sum = a[step*2].sum + a[step*2+1].sum; } void add(int l, int r, int c, int step) { if(l == a[step].l && r == a[step].r) { a[step].sum += c * (a[step].r - a[step].l + 1); a[step].c += c; return; } if(a[step].c != 0) //更新 线段和 { a[step*2].c += a[step].c; a[step*2+1].c += a[step].c; a[step*2].sum += a[step].c * (a[step*2].r - a[step*2].l + 1); a[step*2+1].sum += a[step].c * (a[step*2+1].r - a[step*2+1].l + 1); a[step].c = 0; } int mid = (a[step].l + a[step].r)/2; if(mid >= r) add(l, r, c, step*2); else if(mid < l) add(l, r, c, step*2+1); else { add(l, mid, c, step*2); add(mid+1, r, c, step*2+1); } a[step].sum = a[step*2].sum + a[step*2+1].sum; //递归更新所要加的线段之上的线段和 } __int64 query(int l, int r, int step) { if(l == a[step].l && r == a[step].r) { return a[step].sum; } if(a[step].c != 0) //往下更新,只需更新到你要找的结点就好 { a[step*2].c += a[step].c; a[step*2+1].c += a[step].c; a[step*2].sum += a[step].c * (a[step*2].r - a[step*2].l + 1); a[step*2+1].sum += a[step].c * (a[step*2+1].r - a[step*2+1].l + 1); a[step].c = 0; } int mid = (a[step].l + a[step].r)/2; if(mid >= r) return query(l, r, step*2); else if(mid < l) return query(l, r, step*2+1); else { return query(l, mid, step*2) + query(mid+1, r, step*2+1); } } int main() { int n, m, l, r, c; char s[10]; while(scanf("%d%d", &n, &m) != EOF) { built(1, n, 1); while(m--) { scanf("%s", s); //注意要接受字符串,因为上面的输入缓冲区里还有换行符 if(s[0] == 'Q') { scanf("%d%d", &l, &r); printf("%I64d\n", query(l, r, 1)); } else { scanf("%d%d%d", &l, &r, &c); add(l, r, c, 1); } } } return 0; }
相关文章推荐
- POJ 3468 A Simple Problem with Integers
- POJ 2155 Matrix 3468 A Simple Problem with Integers
- [poj 3468] A Simple Problem with Integers(裸线段树)
- POJ---3468-A Simple Problem with Integers(线段树)
- poj(3468)A Simple Problem with Integers
- Poj 3468 A Simple Problem with Integers【线段树】
- POJ 3468 A Simple Problem with Integers 解题报告
- poj 3468 A Simple Problem with Integers(线段树区区)
- poj-3468-A Simple Problem with Integers-splay树
- POJ 3468 - A Simple Problem with Integers(线段树,区间更新)
- poj 3468 A Simple Problem with Integers(线段树——区间更新)
- POJ 3468 A Simple Problem with Integers // 线段树 区间更新
- POJ 3468 A Simple Problem with Integers
- POJ 3468 A Simple Problem with Integers
- POJ 3468 A Simple Problem with Integers
- poj 3468 A Simple Problem with Integers
- poj 3468 A Simple Problem with Integers
- 线段树 poj 3468 A Simple Problem with Integers 区间add更新
- 区间树 [成段更新] POJ 3468 A Simple Problem with Integers
- POJ 3468 A Simple Problem with Integers(线段树区间更新模板题)