原题链接

题意

  • 初始有一长度为n,全为0的序列

  • 每次我们可以对这个序列进行三种操作:

    • 1.将某个位置的数加上d

    • 2.输出某个区间的和

    • 3.将某个区间内每个数字变为与其最接近的斐波那契数,如果有两个最相近的数,则取更小的那个。

思路

  • 首先对于寻找最近的斐波那契数,我们可以预处理一个90+大小的数组来保存斐波那契数列的前90项,此时范围其实已经要覆盖long long了,完全够用,可以用lower_bound来查询

  • 然后就是这个区间和可以用线段树保存,对于区间的3操作,肯定是不能一个一个去操作的,所以我们可以想到在操作前我们就保存好这个区间的“斐波那契和”。

  • 这样的话,对于每次单点修改操作,我们都要更新一遍线段树路径上的区间和与“斐波那契和”,可以发现,题目中没有区间加和修改的操作,正是我们这种方法得以实行的原因——每次只需要更新一条路上的数据。然后我们使用lazy标记确保3操作的时间复杂度即可。

AC代码

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std; struct ab
{
long long v;
long long fv;
bool fl;
} aa[400005];
int n, m, co = 0; long long fb[1005]; long long abss(long long a)
{
if (a < 0)
{
a = -a;
}
return a;
} void build(int o, int l, int r)
{
aa[o].fl = false;
if (l == r)
{
aa[o].v = 0;
aa[o].fv = 1;
return;
}
int mid = (l + r) >> 1;
build(o << 1, l, mid);
build(o << 1 | 1, mid + 1, r);
aa[o].v = aa[o << 1].v + aa[o << 1 | 1].v;
aa[o].fv = aa[o << 1].fv + aa[o << 1 | 1].fv;
} void pd(int o)
{
if (aa[o].fl)
{
aa[o].fl = false;
aa[o << 1].v = aa[o << 1].fv;
aa[o << 1].fl = true;
aa[o << 1 | 1].v = aa[o << 1 | 1].fv;
aa[o << 1 | 1].fl = true;
}
} void update(int o, int l, int r, int k, long long x)
{
if (l == r)
{
aa[o].v += x;
int ll = lower_bound(fb, fb + 91, aa[o].v) - fb;
if (!ll)
{
aa[o].fv = 1;
}
else if (abss(fb[ll] - aa[o].v) < abss(fb[ll - 1] - aa[o].v))
{
aa[o].fv = fb[ll];
}
else
{
aa[o].fv = fb[ll - 1];
}
return;
}
pd(o);
int mid = (l + r) >> 1;
if (l <= k && mid >= k)
{
update(o << 1, l, mid, k, x);
}
if (mid < k && r >= k)
{
update(o << 1 | 1, mid + 1, r, k, x);
}
aa[o].v = aa[o << 1].v + aa[o << 1 | 1].v;
aa[o].fv = aa[o << 1].fv + aa[o << 1 | 1].fv;
} void change(int o, int l, int r, int x, int y)
{
if (x <= l && y >= r)
{
aa[o].fl = true;
aa[o].v = aa[o].fv;
return;
}
pd(o);
int mid = (l + r) >> 1;
if (x <= mid)
{
change(o << 1, l, mid, x, y);
}
if (y > mid)
{
change(o << 1 | 1, mid + 1, r, x, y);
}
aa[o].v = aa[o << 1].v + aa[o << 1 | 1].v;
aa[o].fv = aa[o << 1].fv + aa[o << 1 | 1].fv;
} long long qu(int o, int l, int r, int x, int y)
{
if (l >= x && r <= y)
{
return aa[o].v;
}
pd(o);
int mid = (l + r) >> 1;
long long ans1 = 0, ans2 = 0;
if (x <= mid)
{
ans1 = qu(o << 1, l, mid, x, y);
}
if (y > mid)
{
ans2 = qu(o << 1 | 1, mid + 1, r, x, y);
}
return ans1 + ans2;
} int main()
{
fb[1] = fb[0] = 1;
for (int i = 2; i <= 90; ++i)
{
fb[i] = fb[i - 2] + fb[i - 1];
}
while (scanf("%d%d", &n, &m) == 2)
{
build(1, 1, n);
for (int i = 1; i <= m; ++i)
{
int q, l, r;
scanf("%d", &q);
if (q == 1)
{
int t;
long long xx;
scanf("%d%lld", &t, &xx);
update(1, 1, n, t, xx);
}
else if (q == 2)
{
scanf("%d%d", &l, &r);
printf("%lld\n", qu(1, 1, n, l, r));
}
else
{
scanf("%d%d", &l, &r);
change(1, 1, n, l, r);
}
}
}
return 0;
}

HDU 4893 线段树延迟标记的更多相关文章

  1. HDU 3468:A Simple Problem with Integers(线段树+延迟标记)

    A Simple Problem with Integers Case Time Limit: 2000MS Description You have N integers, A1, A2, ... ...

  2. hdu 5023 线段树延迟更新+状态压缩

    /* 线段树延迟更新+状态压缩 */ #include<stdio.h> #define N 1100000 struct node { int x,y,yanchi,sum; }a[N* ...

  3. HDU 4893 线段树的 点更新 区间求和

    Wow! Such Sequence! Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Oth ...

  4. HDU 4893 线段树裸题

    Wow! Such Sequence! Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Oth ...

  5. HDU 4893 线段树

    比赛时太大意,斐波拉契数列开小了. 题目大意:1个序列,3种操作,改变序列某个数大小,将序列中连续的一段每个数都变成其最近的斐波拉契数,以及查询序列中某一段的数之和. 解题思路:维护add[]数组表示 ...

  6. Tree(树链剖分+线段树延迟标记)

    Tree http://poj.org/problem?id=3237 Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 12 ...

  7. codevs 1690 开关灯 线段树+延迟标记

    1690 开关灯  时间限制: 1 s  空间限制: 128000 KB   题目描述 Description YYX家门前的街上有N(2<=N<=100000)盏路灯,在晚上六点之前,这 ...

  8. HDU4893--Wow! Such Sequence! (线段树 延迟标记)

    Wow! Such Sequence! Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Oth ...

  9. Jiu Yuan Wants to Eat(树链剖分+线段树延迟标记)

    Jiu Yuan Wants to Eat https://nanti.jisuanke.com/t/31714 You ye Jiu yuan is the daughter of the Grea ...

  10. codevs 2216 行星序列 线段树+延迟标记(BZOJ 1798)

    2216 行星序列  时间限制: 2 s  空间限制: 256000 KB     题目描述 Description “神州“载人飞船的发射成功让小可可非常激动,他立志长大后要成为一名宇航员假期一始, ...

随机推荐

  1. Go语言系列——11-数组和切片、12-可变参数函数、13-Maps、14-字符串、15-指针、16-结构体、17-方法、18-接口(一)、19-接口(二)、19-自定义集合类型、20-并发入门

    文章目录 11-数组和切片 数组 数组的声明 数组是值类型 数组的长度 使用 range 迭代数组 多维数组 切片 创建一个切片 切片的修改 切片的长度和容量 使用 make 创建一个切片 追加切片元 ...

  2. Python面向对象——反射(hasattr、getattr、setattr、delattr)、内置方法(__str__和__del__)、元类(介绍,创建类的流程,exec,自定义元类)、属性查找

    文章目录 反射 内置方法 __str__方法 __del__函数 元类 元类介绍 class关键字创建类的流程分析 补充:exec的用法 自定义元类控制类StanfordTeacher的创建 自定义元 ...

  3. TIPTOP GP ERP二次开发规范说明

    TIPTOP GP ERP二次开发规范说明 TIPTOP ERP共分三大区:topstd(标准区) + toppord(正式区) + toptest(测试区) 标准区                  ...

  4. Go 复合类型之切片类型介绍

    Go 复合类型之切片类型 目录 Go 复合类型之切片类型 一.引入 二.切片(Slice)概述 2.1 基本介绍 2.2 特点 2.3 切片与数组的区别 三. 切片声明与初始化 3.1 方式一:使用切 ...

  5. K8s部署轻量级日志收集系统EFK(elasticsear + filebeat + kibana)

    目录 K8s部署EFK(elasticsear + filebeat + kibana)日志收集 一.准备镜像 二.搭建Elasticsearch + kibana 1.在可执行kubectl命令的服 ...

  6. Caused by: liquibase.exception.ValidationFailedException: Validation Failed:1 change sets check sum

    db/changelog/mysql/changelog-0001-307096-1.0.sql::1.0::buoluo.meng was: 8:a5d8f616a121230c204fd2b878 ...

  7. MyBatis拦截器优雅实现数据脱敏

    背景 现代网络环境中,敏感数据的处理是至关重要的.敏感数据包括个人身份信息.银行账号.手机号码等,泄露这些数据可能导致用户隐私泄露.财产损失等严重后果.因此,对敏感数据进行脱敏处理是一种必要的安全措施 ...

  8. SSL证书链及使用

    什么是证书链 证书链简单来说是域名钥证书.CA公钥.根证书形成的一个颁发链条,属于公钥的一部分. 更白话一点,就是证书链文件包含一系列CA机构公钥的证书. 证书链格式 一般证书链格式是.chain,证 ...

  9. Codeforces Round #700 (Div. 2) A~C题解

    写在前边 链接:Codeforces Round #699 (Div. 2) A. Yet Another String Game 链接:A题链接 题目大意: 给定一个字符串,有两位同学来操作这个字符 ...

  10. 【Javaweb】html frame标签的使用 | 导航栏右侧内容的实现

    问题的产生: 是我和同伴做了一个导航栏,但是我们不知道怎么实现右侧内容的切换 然后我们查了很多资料,但是有一些是垂直的,但是就如图可见,我们是水平的,那么怎么实现水平切换呢? 上网看到了frame标签 ...