hdu4893 Wow! Such Sequence!

线段树结点上保存一个一般的sum值,再同时保存一个fbsum,表示这个结点表示的一段数字若为斐波那契数时的和

当进行3操作时,只用将sum = fbsum即可

其他操作照常进行,只是单点更新的时候也要先向下更新

#include <cstdio>
#include <ctime>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <string>
#include <set>
#include <stack>
#include <map>
#include <cmath>
#include <vector>
#include <iostream>
#include <algorithm>
#include <bitset>
#include <fstream>
using namespace std;
//LOOP
#define FF(i, a, b) for(int i = (a); i < (b); ++i)
#define FE(i, a, b) for(int i = (a); i <= (b); ++i)
#define FED(i, b, a) for(int i = (b); i>= (a); --i)
#define REP(i, N) for(int i = 0; i < (N); ++i)
#define CLR(A,value) memset(A,value,sizeof(A))
#define FC(it, c) for(__typeof((c).begin()) it = (c).begin(); it != (c).end(); it++)
//OTHER
#define SZ(V) (int)V.size()
#define PB push_back
#define MP make_pair
#define all(x) (x).begin(),(x).end()
//INPUT
#define RI(n) scanf("%d", &n)
#define RII(n, m) scanf("%d%d", &n, &m)
#define RIII(n, m, k) scanf("%d%d%d", &n, &m, &k)
#define RIV(n, m, k, p) scanf("%d%d%d%d", &n, &m, &k, &p)
#define RV(n, m, k, p, q) scanf("%d%d%d%d%d", &n, &m, &k, &p, &q)
#define RS(s) scanf("%s", s)
//OUTPUT
#define WI(n) printf("%d\n", n)
#define WS(n) printf("%s\n", n)

#define sqr(x) (x) * (x)
typedef long long LL;
typedef unsigned long long ULL;
typedef vector <int> VI;
const double eps = 1e-9;
const int MOD = 1000000007;
const double PI = acos(-1.0);
//const int INF = 0x3f3f3f3f;
const int maxn = 100010;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;

#define ll rt << 1
#define rr rt << 1 | 1

struct Node{
    int l, r, m;
    LL sum, fbsum;
    bool f;
}t[maxn * 4];
LL fb[10000];
int fbcnt;

void  init()
{
    fb[1] = 1, fb[0] = 1;
    for (int i = 2; ; i++)
    {
        fb[i] = fb[i - 1] + fb[i - 2];
        if (fb[i] > INF)
        {
            fbcnt = i - 1;
            return;
        }
    }
    return;
}

void push_up(int rt)
{
    t[rt].sum = t[ll].sum + t[rr].sum;
    t[rt].fbsum = t[ll].fbsum + t[rr].fbsum;
    t[rt].f = t[ll].f & t[rr].f;
}

LL get(LL x)
{
    int pos = lower_bound(fb, fb + fbcnt, x) - fb;
    if (pos && abs(fb[pos - 1] - x) <= abs(fb[pos] - x))
        return fb[pos - 1];
    return fb[pos];
}

void push_down(int rt)
{
    if (t[rt].f)
    {
        t[ll].sum = t[ll].fbsum;
        t[rr].sum = t[rr].fbsum;
        t[rr].f = t[ll].f = 1;
        t[rt].f = 0;
    }
}

void build(int l, int r, int rt)
{
    t[rt].l = l, t[rt].r = r, t[rt].m = (l + r) >> 1;
    if (l == r)
    {
        t[rt].sum = 0;
        t[rt].fbsum = 1;
        t[rt].f = 0;
        return;
    }
    build(l, t[rt].m, ll);
    build(t[rt].m + 1, r, rr);
    push_up(rt);
}

void update(int x, int add, int rt)
{
    if (x == t[rt].l && t[rt].r == x)
    {
        t[rt].sum += add;
        t[rt].fbsum = get(t[rt].sum);
        t[rt].f = 0;
        return;
    }
    push_down(rt);
    if (x <= t[rt].m)
        update(x, add, ll);
    else
        update(x, add, rr);
    push_up(rt);
}

void updatefb(int l, int r, int rt)
{
    if (l <= t[rt].l && r >= t[rt].r)
    {
        t[rt].sum = t[rt].fbsum;
        t[rt].f = 1;
        return;
    }
    push_down(rt);
    if (l <= t[rt].m)
        updatefb(l, r, ll);
    if (r > t[rt].m)
        updatefb(l, r, rr);
    push_up(rt);
}

LL query(int l, int r, int rt)
{
    if (l <= t[rt].l && r >= t[rt].r)
        return t[rt].sum;
    push_down(rt);
    LL ans = 0;
    if (l <= t[rt].m)
        ans += query(l, r, ll);
    if (r > t[rt].m)
        ans += query(l, r, rr);
    return ans;
}

int main()
{
    init();
    int n, m;
    while (~RII(n, m))
    {
        build(1, n, 1);
        int x, y, op;
        while (m--)
        {
            RIII(op, x, y);
            if (op == 1)
                update(x, y, 1);
            else if (op == 2)
                printf("%I64d\n", query(x, y, 1));
            else
                updatefb(x, y, 1);
        }
    }
    return 0;
}
/*
5 4
3 1 3
2 1 3
1 3 3
2 1 3

5 2
3 1 3
2 1 2
*/

hdu4893 Wow! Such Sequence!

时间: 2024-11-03 13:30:06

hdu4893 Wow! Such Sequence!的相关文章

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

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

Wow! Such Sequence! (线段树) hdu4893

http://acm.hdu.edu.cn/showproblem.php?pid=4893 先贴上一份还没过的代码,不知道拿出错了  1 // by caonima 2 // hehe  3 #include <cstring>  4 #include <algorithm>  5 #include <cstdio>  6 #include <queue>  7 #include <stack>  8 #include <vector&g

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

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 --------------------------------------------------------------------------------------------------------------------------------------------

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>