`
Simone_chou
  • 浏览: 192677 次
  • 性别: Icon_minigender_2
  • 来自: 广州
社区版块
存档分类
最新评论

Wow! Such Sequence!(线段树)

    博客分类:
  • HDOJ
 
阅读更多

Wow! Such Sequence!

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


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
 

 

Author

 

Fudan University

 

       题意:

       给出 n(1 ~ 100000),m (1 ~ 100000) ,代表存在一个初始化为 0 ,数量为 n 的数列,后给出 m 个操作。

       1 a b,代表将数列中第 k 个数增加 b( -2 ^ 31 <= b <= 2 ^ 31);

       2 a b,代表输出数列 a 到 b 的总和;

       3 a b,代表将数列 l 到 r 区间的数更改成最近的斐波那契数。

       输出所有 2 操作的结果。

 

       思路:

       线段树。想预处理斐波那契数,开到 70 足以把所有的数更改为斐波那契数。后线段树维护两个值,sum 为总和值,change 为更改后的总和值,同时运用延迟标记。每次 1 操作只是单纯的单点更新,2 操作查询操作。3 操作的话则延迟标记为 1,代表有需要改变值,同时将 change 的总和赋值给 sum 即可。寻找最近的斐波那契数二分查找即可。

 

       AC:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>

using namespace std;

typedef long long ll;

const int MAXN = 100000;

ll fin[75], sum[MAXN * 3], change[MAXN * 3];
int cover[MAXN * 3];

ll find_min (ll num) {
        if (num <= 0) return fin[1];

        ll it = lower_bound(fin + 1, fin + 70 + 1, num) - fin;

        if (fin[it] == num) return num;

        if (abs(fin[it] - num) < abs(fin[it - 1] - num)) return fin[it];
        return fin[it - 1];
}

void init() {

        fin[1] = 1;
        fin[2] = 1;
        for (ll i = 3; i <= 70; ++i) {
                fin[i] = fin[i - 1] + fin[i - 2];
        }

}

void push_up (ll node) {
        sum[node] = sum[node << 1] + sum[node << 1 | 1];
        change[node] = change[node << 1] + change[node << 1 | 1];
}

void push_down (ll node) {
        if (cover[node] != -1) {
                cover[node << 1] = cover[node << 1 | 1] = cover[node];
                sum[node << 1] = change[node << 1];
                sum[node << 1 | 1] = change[node << 1 | 1];
                cover[node] = -1;
        }
}

void build (ll node, ll l, ll r) {
        if (l == r) {
                sum[node] = 0;
                change[node] = 1;
                cover[node] = -1;
        } else {
                ll mid = (r + l) >> 1;

                build(node << 1, l, mid);
                build(node << 1 | 1, mid + 1, r);

                cover[node] = -1;
                push_up(node);
        }
}

void updata_add (ll node, ll l, ll r, ll k, ll d) {
        if (l == r) {
                if (l == k) {
                        sum[node] += d;
                        change[node] = find_min( sum[node] );
                }
                return;
        }

        push_down(node);
        ll mid = (r + l) >> 1;
        if (k <= mid) updata_add(node << 1, l, mid, k, d);
        else updata_add(node << 1 | 1, mid + 1, r, k, d);
        push_up(node);
}

void updata_change (int node, int l, int r, int cl, int cr) {
        if (cl > r || cr < l) return;
        if (cl <= l && cr >= r) {
                cover[node] = 1;
                sum[node] = change[node];
                return;
        }

        push_down(node);
        ll mid = (r + l) >> 1;
        if (cl <= mid) updata_change(node << 1, l, mid, cl, cr);
        if (cr >= mid + 1) updata_change(node << 1 | 1, mid + 1, r, cl, cr);
        push_up(node);
}

ll query (ll node, ll l, ll r, ll cl, ll cr) {
        if (cl > r || cr < l) return 0;
        if (cl <= l && cr >= r) return sum[node];
        if (r == l) return 0;

        push_down(node);
        ll mid = (r + l) >> 1;
        return query(node << 1, l, mid, cl, cr) +
               query(node << 1 | 1, mid + 1, r, cl, cr);
}

int main() {

        ll n, m;
        init();

        while (~scanf("%I64d%I64d", &n, &m)) {
                build(1, 1, n);

                while (m--) {
                        ll op, a, b;
                        scanf("%I64d%I64d%I64d", &op, &a, &b);

                        if (op == 2) printf("%I64d\n", query(1, 1, n, a, b));
                        else if (op == 1) updata_add(1, 1, n, a, b);
                        else updata_change(1, 1, n, a, b);
                }

        }

        return 0;
}

 

分享到:
评论

相关推荐

    sequence-diagram.zip

    《序列图绘制工具sequence-diagram-js的深度解析与应用》 序列图,作为一种重要的系统建模工具,广泛应用于软件设计和开发中,它清晰地展示了系统内各对象间交互的顺序。sequence-diagram-js是一个基于JavaScript的...

    【hdu5306】Gorgeous Sequence 线段树区间最值操作-附件资源

    【hdu5306】Gorgeous Sequence 线段树区间最值操作-附件资源

    NumberSequence

    在IT行业中,"Number Sequence"通常指的是在特定系统或应用中用于生成自动递增或递减的数字序列。这些序列可以用于唯一标识记录、订单号、发票号等,确保数据的唯一性和可追踪性。在Microsoft Dynamics AX(现称为...

    Activiti 学习笔记七:连线(SequenceFlow)

    在Activiti中,连线(SequenceFlow)是流程图中的重要元素,用于定义活动之间的转移路径。本篇学习笔记将深入探讨SequenceFlow的概念、作用以及如何在流程设计中使用。 一、SequenceFlow简介 SequenceFlow 是 ...

    sequence等同于序列号

    ### Oracle数据库中的Sequence机制详解 #### 一、概述 在Oracle数据库中,`sequence`机制是一种自动生成唯一数值序列的方法,常用于为主键字段提供连续的整数值。它类似于其他数据库系统中的自动增长字段,但在...

    Oracle sequence 重置(失效恢复)

    ### Oracle Sequence 重置(失效恢复) 在进行Oracle数据库移植或维护时,可能会遇到Sequence失效的问题。这种情况通常发生在数据迁移后,原有的Sequence不再与表中的最大值相匹配,导致新记录插入时出现ID冲突或者...

    Sequence to Sequence Learning with Neural Networksv论文

    《Sequence to Sequence Learning with Neural Networks》是一篇由Ilya Sutskever, Oriol Vinyals和Quoc V. Le共同撰写的论文,三位作者都来自Google公司。这篇论文在自然语言处理领域有着重要的影响,特别是在序列...

    SequenceDiagram-3.0.5.zip

    SequenceDiagram-3.0.5.zip 是一个包含 Sequence Diagram 相关工具或资源的压缩包文件,主要用于绘制序列图,这是UML(统一建模语言)中的一种图表,用于描述对象之间的交互和消息传递顺序。在软件开发过程中,序列...

    sequence-to-sequence learning

    机器学习之sequence to sequence learning。(Sequence Generation-----Hung-yi Lee 李宏毅.ppt)

    Sequence简单介绍.pdf

    ### Sequence简单介绍 #### 序列(Sequence)概念解析及应用 序列(Sequence)是一种用于生成一系列数值的数据对象,常用于数据库系统中为主键提供自动递增的功能。本篇文章主要聚焦于Oracle数据库与SQL Server...

    SequenceDiagram.zip

    **序号图(Sequence Diagram)**是统一建模语言(UML)中的一种图形表示,用于描述系统中对象之间的交互顺序。它清晰地展现了不同对象如何通过消息传递进行通信,以及这些消息的时间顺序。在软件设计和分析阶段,...

    oracle中sequence介绍及应用

    ### Oracle中的Sequence介绍及应用 #### 一、Sequence概述 在Oracle数据库中,Sequence是一种用于自动产生数值序列的对象。它可以生成连续的整数或者非连续的整数序列,并且可以根据需求进行递增或递减。Sequence...

    Oracle创建自增字段方法-ORACLE SEQUENCE的简单介绍

    Oracle 创建自增字段方法-ORACLE SEQUENCE 的简单介绍 Oracle SEQUENCE 是一种特殊的数据库对象,用于生成一系列唯一的数值,通常用于主键或其他需要唯一标识的字段。下面将详细介绍 Oracle 创建自增字段方法-...

    oracle中的sequence实现主键增长

    Oracle中的Sequence是数据库管理系统提供的一种机制,用于生成序列化的整数,通常用于主键或唯一标识符,确保数据的唯一性和有序性。在Oracle中,Sequence不同于其他数据库系统的自增字段,例如SQL Server中的`...

    invalid multibyte character sequence 870告警1

    Invalid Multibyte Character Sequence 警告解析 在编程中,特别是在嵌入式系统开发中,我们经常会遇到Invalid Multibyte Character Sequence 警告。这个警告通常来自于编译器,告知我们存在非法的多字节字符序列。...

    Informatica中Sequence Generator的两个有用的选项

    Informatica 中 Sequence Generator 的两个有用的选项 Informatica 是一个功能强大且常用的数据集成工具,在数据集成过程中,Sequence Generator 是一个非常重要的组件,用于生成唯一的序列号,作为表的主键或其他...

Global site tag (gtag.js) - Google Analytics