HDOJ 4893 Wow! Such Sequence! 线段树

http://acm.hdu.edu.cn/showproblem.php?pid=4893

题意:10万的区间,初始都为0,10万次操作,三种操作为单点修改,区间将每个数改成最近的斐波那契数,以及区间求和。

分析:用一个flag记录该段是否被改成斐波那契数,同时多维护一个sum1表示如果该段改成斐波那契数,区间和为多少。开始sum1为区间长度,之后在单点做了修改以后对其更新,需要的时候用其覆盖sum。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 using namespace std;
  5
  6 struct T{
  7     long long sum, sum1;
  8     bool flag;
  9 }t[100100 << 2];
 10 int n, m;
 11 int c, x, y;
 12 long long f[100];
 13 void pushup(int x)
 14 {
 15     int ls = x << 1, rs = x << 1 | 1;
 16     t[x].sum = t[ls].sum + t[rs].sum;
 17     t[x].sum1 = t[ls].sum1 + t[rs].sum1;
 18 }
 19 void pushdown(int x)
 20 {
 21     if (t[x].flag){
 22         t[x<<1].sum = t[x<<1].sum1;
 23         t[x<<1].flag = true;
 24         t[x<<1|1].sum = t[x<<1|1].sum1;
 25         t[x<<1|1].flag = true;
 26         t[x].flag = false;
 27     }
 28 }
 29 void build(int x, int l, int r)
 30 {
 31     t[x].flag = false;
 32     if (l == r){
 33         t[x].flag = t[x].sum = 0;
 34         t[x].sum1 = 1;
 35         return;
 36     }
 37     int mid = l + r >> 1;
 38     build(x<<1, l, mid);
 39     build(x<<1|1, mid+1, r);
 40     pushup(x);
 41 }
 42 void add(int x, int l, int r, int p, long long val)
 43 {
 44     if (l == r){
 45         t[x].sum += val;
 46         if (t[x].sum >= f[91])
 47             t[x].sum1 = f[91];
 48         else if (t[x].sum <= 1)
 49             t[x].sum1 = 1;
 50         else{
 51             long long * p = upper_bound(f, f+92, t[x].sum);
 52             if (t[x].sum - *(p-1) <= *p - t[x].sum)
 53                 t[x].sum1 = *(p-1);
 54             else
 55                 t[x].sum1 = *p;
 56         }
 57         return;
 58     }
 59     int mid = l + r >> 1;
 60     pushdown(x);
 61     if (p <= mid)
 62         add(x<<1, l, mid, p, val);
 63     if (p > mid)
 64         add(x<<1|1, mid+1, r, p, val);
 65     pushup(x);
 66 }
 67 void tra(int x, int l, int r, int s, int e)
 68 {
 69     if (l == r){
 70         t[x].sum = t[x].sum1;
 71         return;
 72     }
 73     if (s <= l && r <= e){
 74         t[x].flag = true;
 75         t[x].sum = t[x].sum1;
 76         return;
 77     }
 78     int mid = l + r >> 1;
 79     pushdown(x);
 80     if (s <= mid)
 81         tra(x<<1, l, mid, s, e);
 82     if (mid < e)
 83         tra(x<<1|1, mid+1, r, s, e);
 84     pushup(x);
 85 }
 86 long long query(int x, int l, int r, int s, int e)
 87 {
 88     if (l == r)
 89         return t[x].sum;
 90     if (s <= l && r <= e)
 91         return t[x].sum;
 92     long long tmp = 0;
 93     int mid = l + r >> 1;
 94     pushdown(x);
 95     if (s <= mid)
 96         tmp += query(x<<1, l, mid, s, e);
 97     if (mid < e)
 98         tmp += query(x<<1|1, mid+1, r, s, e);
 99     pushup(x);
100     return tmp;
101 }
102 int main()
103 {
104     f[0] = 1; f[1] = 1;
105     for (int i = 2; i <= 91; i++)
106         f[i] = f[i-1] + f[i-2];
107     while(scanf("%d %d", &n, &m) != EOF)
108     {
109         build(1, 1, n);
110         while(m--){
111             scanf("%d %d %d", &c, &x, &y);
112             if (c == 1) add(1, 1, n, x, (long long)y);
113             if (c == 2) printf("%I64d\n", query(1, 1, n, x, y));
114             if (c == 3) tra(1, 1, n, x, y);
115         }
116     }
117     return 0;
118 }

HDOJ 4893 Wow! Such Sequence! 线段树,布布扣,bubuko.com

时间: 2024-08-03 15:44:08

HDOJ 4893 Wow! Such Sequence! 线段树的相关文章

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

题目链接:hdu 4983 Wow! Such Sequence! 题目大意:就是三种操作 1 k d, 修改k的为值增加d 2 l r, 查询l到r的区间和 3 l r, 间l到r区间上的所以数变成最近的斐波那契数,相等的话取向下取. 解题思路:线段树,对于每个节点新增一个bool表示该节点以下的位置是否都是斐波那契数. #include <cstdio> #include <cstring> #include <cstdlib> #include <algor

HDU 4893 Wow! Such Sequence 线段树暴力

题意:n个数 初始为0,三个操作:给某个数加上d,查询区间和,把区间[l,r]中每个a[i]变为离a[i]最近的斐波那契数,n,m<=1e5. 无操作1情况下,每个点最多变化一次,每次修改logn,算上操作1 最坏情况下修改n+m次 O((n+m)logn). 对区间设个标记 线段树暴力即可. #include <bits/stdc++.h> using namespace std; typedef long long ll; const ll mod=1e9+7; const int

hdu 4893 (多校1007)Wow! Such Sequence!(线段树&amp;二分&amp;思维)

Wow! Such Sequence! Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 352    Accepted Submission(s): 104 Problem Description Recently, Doge got a funny birthday present from his new friend, Prot

HDOJ 4893 Wow! Such Sequence!

题意是这样的,给定一个n个元素的数组,初始值为0,3种操作: 1 k d将第k个数增加d: 2 l r 询问区间l...r范围内数之和: 3 l r 表示将区间l...r内的数变成离他最近的斐波那契数,要求尽量小. 线段树操作题目,其中对于第三种操作用一个懒惰标记一下,表示l...r内的数是不是已经变成斐波那契数,如果是的话,求和就是其相应数的斐波那契数之和. 代码: 1 //Template updates date: 20140718 2 #include <bits/stdc++.h>

2014多校3 Wow! Such Sequence!线段树

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4893 这题实在是让人纠结啊--好久不写线段树的题了,因为这几天学伸展树,然后觉得线段树小case了.没想到栽在这题上了.尼玛-- 自己把自己给搞晕了--想复杂了,都不懂得预处理一下,唉--还得怒刷几十道啊!! #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #in

HDU4893 Wow! Such Sequence! 线段树

题意:给你一个序列,其中有三种操作 1)位置为K 的数+ D 2)求 l-r 区间和 3)把 l-r 区间里面的所有数都变为理它最近的斐波纳契数 解题思路:这个题的区间更新其实可以在单点更新的时候就得出,为节点维护两个 和,一个是 斐波纳契和 一个是正常和 ,再看这个区间有没有被3覆盖,特判一下就行了. 解题代码: 1 // File Name: 1007.cpp 2 // Author: darkdream 3 // Created Time: 2014年07月29日 星期二 12时49分33

HDU4893:Wow! Such Sequence!(线段树lazy)

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 nu

HDU 4893 Wow! Such Sequence! 水线段树

思路: 线段树走起.. 写完这题就退役T^T 单点更新的时候直接找到这个点的最近fib,然后维护当前和 和 fib的和 #include<stdio.h> #include<string.h> #include<iostream> #include<math.h> #include<algorithm> #include<queue> #include<map> #include<set> #include&l

hdu 4893 Wow! Such Sequence!(线段树功能:单点更新,区间更新相邻较小斐波那契数)

转载请注明出处:http://blog.csdn.net/u012860063?viewmode=contents 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4893 --------------------------------------------------------------------------------------------------------------------------------------------