标签:线段树
1 1 2 1 1 5 4 1 1 7 1 3 17 3 2 4 2 1 5
0 22
题意:
题目中说对一个长度为n,初始元素都为0的数组进行三种操作,如下:
1 k d 第 k 个元素加上 d
2 l r 求从 l 到 r 所有元素的和
3 l r 改变从 l 到 r 所有元素,都为原元素最近的 Fibonacci 数,差值相等时取较小值
思路:
对于第一个操作需要用到线段树中的单点更新操作,对于第二个操作需要用到线段树中的区间求和操作,对于第三个操作需要思考一下,怎么处理才能最快地改变我们需要改变区间的状态。因为对于区间有个求和操作,那么我们会考虑到只需要改变一段区间的和即可。处理的方案就是提前对每一段的 区间和 都找到相应的 Fibonacci 数作为映射,那么我们要对区间进行第三操作时,只需要将区间做一下标记,然后将这个映射值覆盖到原 区间和 即可。
注意点:
1.注意 pushdown 和 pushup 的使用。
2.注意当访问到叶子节点时最好是返回(return),若不返回那么开大线段树的大小(原为4倍)也行。
3.注意杭电的输出为 %I64。
/************************************************************************* > File Name: 1007.cpp > Author: Bslin > Mail: Baoshenglin1994@gmail.com > Created Time: 2014年07月29日 星期二 13时07分08秒 ************************************************************************/ #include <cstdio> #include <cmath> using namespace std; #define N 100010 struct node { int L, R; long long sum, vsum; int flag; } tree[N << 2]; long long ans; long long ffib(long long val) { long long x = 0, y = 1; int i; for (i = 0; i < 100; ++i) { y = x + y; x = y - x; if(y >= val) break; } if(fabs(y - val) < fabs(x - val)) return y; return x; } void PushUP(int p) { if(tree[p].L == tree[p].R) return; tree[p].sum = tree[p << 1].sum + tree[p << 1 | 1].sum; tree[p].vsum = tree[p << 1].vsum + tree[p << 1 | 1].vsum; } void PushDown(int p) { if(tree[p].flag && tree[p].L == tree[p].R) { tree[p].sum = tree[p].vsum; tree[p].flag = 0; return ; } if(tree[p].flag) { tree[p << 1].flag = tree[p << 1 | 1].flag = 1; tree[p << 1].sum = tree[p << 1].vsum; tree[p << 1 | 1].sum = tree[p << 1 | 1].vsum; tree[p].flag = 0; } } void build(int L, int R, int p) { tree[p].L = L; tree[p].R = R; tree[p].flag = 0; if(L == R) { tree[p].sum = 0; tree[p].vsum = 1; return ; } int mid = (L + R) >> 1; build(L, mid, p << 1); build(mid + 1, R, p << 1 | 1); PushUP(p); } void add(int pos, int val, int p) { if (tree[p].L == tree[p].R) { tree[p].sum += val; tree[p].vsum = ffib(tree[p].sum); tree[p].flag = 0; return ; } PushDown(p); int mid = (tree[p].L + tree[p].R) >> 1; if (mid >= pos) add(pos, val, p << 1); else add(pos, val, p << 1 | 1); PushUP(p); } void update(int L, int R, int p) { if (L <= tree[p].L && R >= tree[p].R) { tree[p].flag = 1; tree[p].sum = tree[p].vsum; return ; } PushDown(p); int mid = (tree[p].L + tree[p].R) >> 1; if (mid >= R) update(L, R, p << 1); else if (mid + 1 <= L) update(L, R, p << 1 | 1); else { update(L, mid, p << 1); update(mid + 1, R, p << 1 | 1); } PushUP(p); } void query(int L, int R, int p) { if (L <= tree[p].L && R >= tree[p].R) { ans += tree[p].sum; return ; } PushDown(p); int mid = (tree[p].L + tree[p].R) >> 1; if (mid >= R) query(L, R, p << 1); else if (mid + 1 <= L) query(L, R, p << 1 | 1); else { query(L, mid, p << 1); query(mid + 1, R, p << 1 | 1); } PushUP(p); } int main(int argc, char *argv[]) { freopen("in.txt", "r", stdin); int n, m, i; int op, x, y; while(scanf("%d%d", &n, &m) != EOF) { build(1, n, 1); for (i = 0; i < m; ++i) { scanf("%d%d%d", &op, &x, &y); if(op == 1) { add(x, y, 1); } else if(op == 2) { ans = 0; query(x, y, 1); printf("%I64d\n", ans); // hdu } else if(op == 3) { update(x, y, 1); } } } return 0; }
HDU 4893 Wow! Such Sequence! (线段树),布布扣,bubuko.com
HDU 4893 Wow! Such Sequence! (线段树)
标签:线段树
原文地址:http://blog.csdn.net/u012150279/article/details/38278785