HDU 4893 Wow! Such Sequence! (线段树单点更新+区间更新+区间查询+二分)
2016-07-09 10:04
274 查看
Wow! Such Sequence!
[align=center]Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 4116 Accepted Submission(s): 1174
[/align]
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.
[align=left]Input[/align]
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.
[align=left]Output[/align]
For each Type 2 ("query sum") operation, output one line containing an integer represent the answer of this query.
[align=left]Sample Input[/align]
1 1
2 1 1
5 4
1 1 7
1 3 17
3 2 4
2 1 5
[align=left]Sample Output[/align]
0
22
[align=left]Author[/align]
Fudan University
[align=left]Source[/align]
2014 Multi-University Training
Contest 3
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4893
题目大意:给一个数列,三种操作,1是将k位置增加d,2是查询区间l到r中的数字和,3是将l到r中的数字都变成离它最近的斐波那契数
题目分析:操作1是单点更新,2是区间查询,3是区间更新,1和2都是裸的,3的话考虑到变化以后只对查询的结果有影响,因此可以加一个数组在单点更新的时候记录和fib的差值,fib预处理然后二分找一下,然后pushup得到区间差值和,这样区间更新直接加就好了,因为若两个3操作间没有1操作,这样数列其实是没有变化的,故更新过一次要将区间差值和置0
#include <cstdio> #include <cstring> #include <algorithm> #define ll long long #define lson l, mid, rt << 1 #define rson mid + 1, r, rt << 1 | 1 using namespace std; int const MAX = 1e5 + 5; ll sum[MAX << 2], extra[MAX << 2]; ll fib[95]; bool lazy[MAX << 2]; int n, m; void Fib() { fib[0] = 1; fib[1] = 1; for(int i = 2; i < 90; i++) fib[i] = fib[i - 1] + fib[i - 2]; } ll Get_extra(ll x) { if(x <= 1) return 1; int p = lower_bound(fib, fib + 90, x) - fib; return (x - fib[p - 1] <= fib[p] - x) ? fib[p - 1] : fib[p]; } void PushUp(int rt) { sum[rt] = sum[rt << 1] + sum[rt << 1 | 1]; extra[rt] = extra[rt << 1] + extra[rt << 1 | 1]; } void PushDwon(int rt) { if(lazy[rt]) { sum[rt << 1] += extra[rt << 1]; sum[rt << 1 | 1] += extra[rt << 1 | 1]; extra[rt << 1] = 0; extra[rt << 1 | 1] = 0; lazy[rt << 1] = true; lazy[rt << 1 | 1] = true; lazy[rt] = false; } } void Build(int l, int r, int rt) { lazy[rt] = false; sum[rt] = 0; if(l == r) { extra[rt] = 1; return; } int mid = (l + r) >> 1; Build(lson); Build(rson); PushUp(rt); } void Update1(int k, ll d, int l, int r, int rt) { if(l == r) { sum[rt] += (ll)d; extra[rt] = Get_extra(sum[rt]) - sum[rt]; return; } int mid = (l + r) >> 1; PushDwon(rt); if(k <= mid) Update1(k, d, lson); else Update1(k, d, rson); PushUp(rt); } void Update2(int L, int R, int l, int r, int rt) { if(L <= l && r <= R) { sum[rt] += extra[rt]; extra[rt] = 0; lazy[rt] = true; return; } int mid = (l + r) >> 1; PushDwon(rt); if(L <= mid) Update2(L, R, lson); if(mid < R) Update2(L, R, rson); PushUp(rt); return; } ll Query(int L, int R, int l, int r, int rt) { if(L <= l && r <= R) return sum[rt]; int mid = (l + r) >> 1; PushDwon(rt); ll ans = 0; if(L <= mid) ans += Query(L, R, lson); if(mid < R) ans += Query(L, R, rson); return ans; } int main() { Fib(); while(scanf("%d %d", &n, &m) != EOF) { int tp; Build(1, n, 1); while(m --) { scanf("%d", &tp); if(tp == 1) { int k; ll d; scanf("%d %I64d", &k, &d); Update1(k, d, 1, n, 1); } else if(tp == 2) { int x, y; scanf("%d %d", &x, &y); printf("%I64d\n", Query(x, y, 1, n, 1)); } else { int x, y; scanf("%d %d", &x, &y); Update2(x, y, 1, n, 1); } } } }
相关文章推荐
- 使用GPUImage实现视频滤镜
- poj 2299 Ultra QuickSort 树状数组+离散化
- String StringBuffer和StringBuilder
- HDU 5301 Buildings (乱搞)
- Codeforces 689D Friends and Subsequences(RMQ+二分)
- [leetcode]62. Unique Paths
- 2016 UESTC Training for Math G - 完美点集 解方程
- 2016 UESTC Training for Math F - 粗心的谭爷 素数线性筛法的推广
- 2016 UESTC Training for Math D - 熄灯啦! 讨论
- 2016 UESTC Training for Math A - 谭爷的黑暗沙拉 组合学
- There is no getter for property named 'xxx' in 'class com.xuezhixin.mls.web.model.yyy
- Segment Tree Query I & II
- Segment Tree Build I & II
- EasyUI Pagination 分页的两种做法小结
- 从用户行为到用户界面的最后一道门:分析与计算
- MySQL Packet for query is too large
- weui2
- Quick Look Framework
- 【Arduino官方教程】数字处理示例(四):输入上拉
- 用UIBezierPath数组对UIView进行镂空处理