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 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
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define ll __int64
#define maxn 100005
#define ls l,mid,2*i
#define rs mid+1,r,2*i+1
#define lson 2*i
#define rson 2*i+1
struct node
{
    int l,r;
    ll e,f;//e为该区间的和,f为其近期的斐波那契数
    int flag,len;//flag,标记这个区间内是否斐波那契数,len为长度
} a[maxn<<2];
int n,m;
ll f[90] = {1,1};

ll pabs(ll a)
{
    return a<0?-a:a;
}

void PushDown(int i,int m)
{
    if(a[i].flag)
    {
        a[lson].flag = a[rson].flag = a[i].flag;
        a[lson].len = a[i].flag*(m-m>>1);
        a[rson].len = a[i].flag*(m>>1);
        a[lson].e = a[lson].f;
        a[rson].e = a[rson].f;
        a[i].flag = 0;
    }
}

void PushUp(int i)
{
    a[i].e = a[lson].e+a[rson].e;
    a[i].f = a[lson].f+a[rson].f;
}

void init(int l,int r,int i)
{
    a[i].flag = a[i].len = 0;
    a[i].l = l;
    a[i].r = r;
    a[i].e = 0;
    if(l == r)
    {
        a[i].f = 1;
        return;
    }
    int mid = (l+r)>>1;
    init(ls);
    init(rs);
    PushUp(i);
}

void add(int pos,int m,int l,int r,int i)
{
    if(pos<l || pos>r) return ;
    if(l == r)
    {
        if(a[i].flag)
        {
            a[i].e = m+a[i].f;
            a[i].flag = 0;
            a[i].len = 0;
        }
        else a[i].e+=m;
        int p = lower_bound(f,f+80,a[i].e)-f;
        if(!p)
            a[i].f = 1;
        else if(pabs(a[i].e-f[p])<pabs(a[i].e-f[p-1]))
            a[i].f = f[p];
        else
            a[i].f = f[p-1];
        return ;
    }
    PushDown(i,r-l+1);
    int mid = (l+r)>>1;
    if(pos<=mid) add(pos,m,ls);
    else add(pos,m,rs);
    PushUp(i);
}

ll query(int L,int R,int l,int r,int i)
{
    if(R<l || L>r) return 0;
    else if(L<=l && R>=r) return a[i].e;
    PushDown(i,r-l+1);
    ll ans = 0;
    int mid = (l+r)>>1;
    if(L<=mid)
        ans += query(L,R,ls);
    if(R>mid)
        ans += query(L,R,rs);
    return ans;
}

void change(int L,int R,int l,int r,int i)
{
    if(R<l || L>r) return ;
    if(L<=l && R>=r)
    {
        a[i].e = a[i].f;
        a[i].flag = 1;
        a[i].len = r-l+1;
        return ;
    }
    PushDown(i,r-l+1);
    int mid = (l+r)>>1;
    if(L<=mid)
        change(L,R,ls);
    if(R>mid)
        change(L,R,rs);
    PushUp(i);
}

int main()
{
    int i,j,x,k,d,l,r;
    for(i = 2; i<80; i++)
        f[i] = f[i-1]+f[i-2];
    while(~scanf("%d%d",&n,&m))
    {
        init(1,n,1);
        while(m--)
        {
            scanf("%d",&x);
            if(x == 1)
            {
                scanf("%d%d",&k,&d);
                add(k,d,1,n,1);
            }
            else
            {
                scanf("%d%d",&l,&r);
                if(x == 2)
                    printf("%I64d\n",query(l,r,1,n,1));
                else
                    change(l,r,1,n,1);
            }
        }
    }

    return 0;
}
时间: 2024-08-25 01:40:10

HDU4893:Wow! Such Sequence!(段树lazy)的相关文章

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

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

2014多校3 Wow! Such Sequence!段树

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

hdu4893 Wow! Such Sequence!

线段树结点上保存一个一般的sum值,再同时保存一个fbsum,表示这个结点表示的一段数字若为斐波那契数时的和 当进行3操作时,只用将sum = fbsum即可 其他操作照常进行,只是单点更新的时候也要先向下更新 #include <cstdio> #include <ctime> #include <cstdlib> #include <cstring> #include <queue> #include <string> #incl

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 (多校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! 线段树

http://acm.hdu.edu.cn/showproblem.php?pid=4893 题意:10万的区间,初始都为0,10万次操作,三种操作为单点修改,区间将每个数改成最近的斐波那契数,以及区间求和. 分析:用一个flag记录该段是否被改成斐波那契数,同时多维护一个sum1表示如果该段改成斐波那契数,区间和为多少.开始sum1为区间长度,之后在单点做了修改以后对其更新,需要的时候用其覆盖sum. 1 #include<cstdio> 2 #include<cstring>

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

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

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