标签:线段树
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