题目链接[http://acm.hdu.edu.cn/showproblem.php?pid=4893]

题意:输入n、q。表示有n个数,初始化默认这n个数都为零,有q次操作,操作种类分为三种:1、输入k,d,使得k位置的数加上d。2、输入l,r,求区间[l,r]的和并输出。3、输入l,r,把区间[l,r]内的数都改成斐波拉契数,修改方式为使得fabs[x-F[i]]最小,如果有多个F[i]满足情况,用最小的那个F[i]。1 ≤ n ≤ 100000, 1 ≤ m ≤ 100000, |d| < 231。

题解:对于前两种操作,可以用单点更新来维护,但是对于第三种操作如果用单点更新的话,会TLE(n^2),所以我们要区间更新,我们要很快的知道区间[l,r]区间的FIB和,索性我们就在线段树里维护所有数的FIB和,在build,和操作一的时候更新就可以了。时间复杂度n*log(n)。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = ;
int n, m;
struct node
{
int l, r;
LL sm1, sm2;
bool t;
} T[maxn << ];
LL F[];
void init()
{
F[] = F[] = ;
for(int i = ; i <= ; i++)
F[i] = F[i - ] + F[i - ];
}
LL FBI(LL x)
{
int pos = (int)(lower_bound(F, F + , x) - F);
if(!pos) return F[];
else
{
LL t1 = F[pos] - x;
LL t2 = x - F[pos - ];
if(t1 < t2)
return F[pos];
else
return F[pos - ];
}
}
void pushup(int id)
{
T[id].sm1 = T[id << ].sm1 + T[id << | ].sm1;
T[id].sm2 = T[id << ].sm2 + T[id << | ].sm2;
}
void pushdown(int id)
{
if(T[id].t)
{
T[id << ].sm1 = T[id << ].sm2;
T[id << ].t = ;
T[id << | ].sm1 = T[id << | ].sm2;
T[id << | ].t = ;
T[id].t = ;
}
}
void build(int id, int l, int r)
{
T[id].l = l;
T[id].r = r;
T[id].t = ;
if(l == r)
{
T[id].sm1 = ;
T[id].sm2 = ;
return ;
}
else
{
int mid = (l + r) >> ;
build(id << , l, mid);
build(id << | , mid + , r);
pushup(id);
}
}
LL sum(int id, int l, int r)
{
if(T[id].l == l && T[id].r == r)
return T[id].sm1;
else
{
pushdown(id);
int mid = (T[id].l + T[id].r) >> ;
if(r <= mid)
return sum(id << , l, r);
else if(l >= mid + )
return sum(id << | , l, r);
else
return sum(id << , l, mid) + sum(id << | , mid + , r);
}
}
void change(int id, int l, int r)
{
if(T[id].l == l && T[id].r == r)
{
T[id].sm1 = T[id].sm2;
T[id].t = ;
return ;
}
else
{
pushdown(id);
int mid = (T[id].l + T[id].r) >> ;
if(r <= mid)
{
change(id << , l, r);
}
else if(l >= mid + )
{
change(id << | , l, r);
}
else
{
change(id << , l, mid);
change(id << | , mid + , r);
}
pushup(id);
}
}
void update(int id, int pos, LL d)
{
if(T[id].l == T[id].r)
{
T[id].sm1 += d;
T[id].sm2 = FBI(T[id].sm1);
return ;
}
else
{
pushdown(id);
int mid = (T[id].l + T[id].r) >> ;
if(pos <= mid)
update(id << , pos, d);
else
update(id << | , pos, d);
pushup(id);
}
}
int main()
{
init();
while(scanf("%d%d", &n, &m) != EOF)
{
build(, , n);//
LL d;
int k, l, r, ty;
for(int i = ; i <= m; i++)
{
scanf("%d", &ty);
if(ty == )
{
scanf("%d%lld", &k, &d);
update(, k, d);
}
else if(ty == )
{
scanf("%d%d", &l, &r);
printf("%lld\n", sum(, l, r));
}
else
{
scanf("%d%d", &l, &r);
change(, l, r);
}
}
}
return ;
}

HDU4893【线段树单点、区间更新】的更多相关文章

  1. 2019hdu多校3 hdu4893(线段树单点 区间更新

    补这题主要是因为第三个操作要维护区间,而不是点,否则会T. https://vjudge.net/problem/HDU-4893 题意:输入n.q.表示有n个数,初始化默认这n个数都为零,有q次操作 ...

  2. 蓝桥杯Log大侠(线段树单点区间更新)

    标题:Log大侠 atm参加了速算训练班,经过刻苦修炼,对以2为底的对数算得飞快,人称Log大侠. 一天,Log大侠的好友 drd 有一些整数序列需要变换,Log大侠正好施展法力... 变换的规则是: ...

  3. hdu 1556:Color the ball(线段树,区间更新,经典题)

    Color the ball Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  4. hdu 1698:Just a Hook(线段树,区间更新)

    Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  5. UVA 12436-Rip Van Winkle's Code(线段树的区间更新)

    题意: long long data[250001]; void A( int st, int nd ) { for( int i = st; i \le nd; i++ ) data[i] = da ...

  6. hdu1698线段树的区间更新区间查询

    Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Tota ...

  7. HDU 1556 Color the ball(线段树:区间更新)

    http://acm.hdu.edu.cn/showproblem.php?pid=1556 题意: N个气球,每次[a,b]之间的气球涂一次色,统计每个气球涂色的次数. 思路: 这道题目用树状数组和 ...

  8. zoj3686(线段树的区间更新)

    对线段树的区间更新有了初步的了解... A Simple Tree Problem Time Limit: 3 Seconds      Memory Limit: 65536 KB Given a ...

  9. Color the ball (线段树的区间更新问题)

    N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <= b),lele便为骑上他的“小飞鸽"牌电动车从气球a开始到气球b依次给每个气球涂一次颜色.但 ...

  10. ZOJ 2301 Color the Ball 线段树(区间更新+离散化)

    Color the Ball Time Limit: 2 Seconds      Memory Limit: 65536 KB There are infinite balls in a line ...

随机推荐

  1. CSS基础复习

    重新撸一遍CSS的基础,因为以前面试的时候被问到,突然发现某些概念搞不清楚,瞬间懵逼了,其实我都知道的,就是因为不会炒概念,导致面试官觉得我很low,你特么连这个都不知道还敢来面试,回家种田去好嘛! ...

  2. Java并发编程学习路线

    一年前由于工作需要从微软技术栈入坑Java,并陆陆续续做了一个Java后台项目,目前在搞Scala+Java混合的后台开发,一直觉得并发编程是所有后台工程师的基本功,所以也学习了小一年Java的并发工 ...

  3. Spring Boot中使用MongoDB数据库

    前段时间分享了关于Spring Boot中使用Redis的文章,除了Redis之后,我们在互联网产品中还经常会用到另外一款著名的NoSQL数据库MongoDB. 下面就来简单介绍一下MongoDB,并 ...

  4. MyBatis数据库字段和实体对象属性名不一致的解决方案

    数据库和对象的属性名不一致是很常见的问题,这个时候依从表字段到对象属性名的按名称匹配映射已经搞不定这个了,下面是几种解决方案. 1. 开启驼峰转换 如果数据库中的字段名与对象只是简单的不一致的话,比如 ...

  5. 爬虫实战--基于requests 和 Beautiful的7160美图网爬取图片

    import requests import os from bs4 import BeautifulSoup import re # 初始地址 all_url = 'http://www.7160. ...

  6. idea 控制台乱码

    第一步:修改intellij idea配置文件: 找到intellij idea安装目录,bin文件夹下面idea64.exe.vmoptions和idea.exe.vmoptions这两个文件,分别 ...

  7. gmail注册时“此电话号码无法用于进行验证”

    网上有几个方法,有说不要改默认地点,有说验证时直接写+86手机号,试了以后还是不行. 我的方法:换成IE浏览器,就可以验证了.

  8. 在Perl中使用Getopt::Long模块来接收用户命令行参数

    我们在linux常常用到一个程序需要加入参数,现在了解一下perl中的有关控制参数的函数.getopt.在linux有的参数有二种形式.一种是–help,另一种是-h.也就是-和–的分别.–表示完整参 ...

  9. python3.x的HTMLTestRunner.py文件

    """A TestRunner for use with the Python unit testing framework. Itgenerates a HTML re ...

  10. 从LabVIEW到C++

    前言 最近一段时间一直没有更新,一方面是时间精力的问题(PS:懒癌犯了),另一方面是小黑大部分的时间都在学习C++相关知识,恶补了许多的知识(从大学C语言水平强制拔高了一段). 本文谈谈自己近期的一些 ...