HDU 4893 Wow! Such Sequence! (线段树)

Wow! Such Sequence!

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 838    Accepted Submission(s): 245



Problem Description
Recently, Doge got a funny birthday present from his new friend, Protein Tiger from St. Beeze College. No, not cactuses. It's a mysterious blackbox.

After some research, Doge found that the box is maintaining a sequence an of n numbers internally, initially all numbers are zero, and there are THREE "operations":

1.Add d to the k-th number of the sequence.
2.Query the sum of ai where l ≤ i ≤ r.
3.Change ai to the nearest Fibonacci number, where l ≤ i ≤ r.
4.Play sound "Chee-rio!", a bit useless.

Let F0 = 1,F1 = 1,Fibonacci number Fn is defined as Fn = Fn - 1 + Fn - 2 for n ≥ 2.

Nearest Fibonacci number of number x means the smallest Fn where |Fn - x| is also smallest.

Doge doesn't believe the machine could respond each request in less than 10ms. Help Doge figure out the reason.
 

Input
Input contains several test cases, please process till EOF.
For each test case, there will be one line containing two integers n, m.
Next m lines, each line indicates a query:

1 k d - "add"
2 l r - "query sum"
3 l r - "change to nearest Fibonacci"

1 ≤ n ≤ 100000, 1 ≤ m ≤ 100000, |d| < 231, all queries will be valid.
 

Output
For each Type 2 ("query sum") operation, output one line containing an integer represent the answer of this query.
 

Sample Input
1 1 2 1 1 5 4 1 1 7 1 3 17 3 2 4 2 1 5
 

Sample Output
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
", ans);  // hdu
			} else if(op == 3) {
				update(x, y, 1);
			}
		}
	}
	return 0;
}


原文地址:https://www.cnblogs.com/mthoutai/p/6773402.html