线段树之单点更新,区域求和
今天在coreforces上做的一题
4 seconds
256 megabytes
standard input
standard output
In mathematical terms, the sequence Fn of Fibonacci numbers is defined by the recurrence relation
F1 = 1; F2 = 1; Fn = Fn - 1 + Fn - 2 (n > 2).
DZY loves Fibonacci numbers very much. Today DZY gives you an array consisting of n integers: a1, a2, ..., an. Moreover, there are mqueries, each query has one of the two types:
- Format of the query "1 l r". In reply to the query, you need to add Fi - l + 1 to each element ai, where l ≤ i ≤ r.
- Format of the query "2 l r". In reply to the query you should output the value of modulo 1000000009 (109 + 9).
Help DZY reply to all the queries.
The first line of the input contains two integers n and m (1 ≤ n, m ≤ 300000). The second line contains n integers a1, a2, ..., an (1 ≤ ai ≤ 109) — initial array a.
Then, m lines follow. A single line describes a single query in the format given in the statement. It is guaranteed that for each query inequality 1 ≤ l ≤ r ≤ n holds.
For each query of the second type, print the value of the sum on a single line.
4 4 1 2 3 4 1 1 4 2 1 4 1 2 4 2 1 3
17 12
After the first query, a = [2, 3, 5, 7].
For the second query, sum = 2 + 3 + 5 + 7 = 17.
After the third query, a = [2, 4, 6, 9].
For the fourth query, sum = 2 + 4 + 6 = 12.
大意:用fib去加到每个节点,求区域的和
代码如下:
#include <cstdio>
#include <cmath>
#include <iostream>
using namespace std;const int MAXNODE = 2097152; // == (1 << 21) - 1 depth:21
const int MAXS = 300003;
struct SOILD{int left,right; // 数组模拟满二叉树, 区间 [left,right]long value;
}Soldier[MAXNODE];
long fib[300005];
int father[MAXS]; // 存每一个士兵的父结点void BuildTree(int i,int left,int right,int devalue){ // 初始值为0Soldier[i].left = left;Soldier[i].right = right;Soldier[i].value = devalue;if (left == right){father[left] = i; // 可以瞬间知道第i个士兵的父节点是哪个return;}BuildTree(i*2, left, (int)floor((right+left)/2.0), 0);BuildTree(i*2+1, (int)floor((right+left)/2.0)+1, right, 0);
}void UpdataTree(int ri,int iKilln){ // 单点更新: 点p[i,i] 更新为iKilln (初始为0)if (ri == 1){Soldier[ri].value += iKilln;return;}Soldier[ri].value += iKilln; // iKilln 设为全局变量应该快一点UpdataTree(ri/2,iKilln);
}long res;
void Query(int i,int a,int b){ // [a,b]区间的和if (a == Soldier[i].left && b == Soldier[i].right){res += Soldier[i].value;return ;}if (a <= Soldier[i*2].right){ // 左端点小于右端点(几何含义:区间横跨过中点) 则区间需要分割if (b <= Soldier[i*2].right){Query(i*2, a, b); // 左边全包含}else{Query(i*2, a, Soldier[i*2].right); // 横跨取左}}if (b >= Soldier[i*2+1].left){if (a >= Soldier[i*2+1].left){Query(i*2+1, a, b); // 右边全包含}else{Query(i*2+1, Soldier[i*2+1].left, b); // 横跨取右}}
}int main(){int n_s,n_q;long iKilln,a,b;cin >> n_s >> n_q;BuildTree(1,1,n_s,0);fib[1]=1;fib[2]=1;for(int k2=3;k2<300005;k2++){fib[k2]=fib[k2-1]+fib[k2-2];}for (int ii = 1 ;ii <= n_s; ii++){ // 建树scanf("%d",&iKilln); // iKilln 为第 i 个增加的杀敌数UpdataTree(father[ii],iKilln); // 瞬间找到士兵的结点序号}int order;for (int i = 1; i <= n_q; i++){scanf("%d%d%d",&order,&a,&b); // [a,b] ; a + kill b if (order==2){res = 0;Query(1,a,b);printf("%d\n", res);}else{for(int kk=a;kk<=b;kk++)UpdataTree(father[kk],fib[kk-a+1]);}//for(int ttt=1;ttt<=n_s;ttt++)// printf("%d;;",Soldier[father[ttt]].value);// printf("\n");}return 0;
}
要取 long long/__int64;
版权声明:本文为博主原创文章,未经博主允许不得转载。
转载于:https://www.cnblogs.com/france/p/4808782.html
线段树之单点更新,区域求和相关推荐
- hdu 1166 敌兵布阵(线段树之 单点更新+区间求和)
敌兵布阵 Time Limit: 2000/10 ...
- HDUOJ---1754 I Hate It (线段树之单点更新查区间最大值)
I Hate It Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total ...
- HDU 1394 Minimum Inversion Number(线段树的单点更新)
点我看题目 题意 :给你一个数列,a1,a2,a3,a4.......an,然后可以求出逆序数,再把a1放到an后,可以得到一个新的逆序数,再把a2放到a1后边,,,,,,,依次下去,输出最小的那个逆 ...
- [ACM] hdu 1754 I Hate It (线段树,单点更新)
I Hate It Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total ...
- 线段树(单点更新(模板)) 之 hdu 1166
// [7/24/2014 Sjm] /* 第一道用线段树做的题,照着大神的代码风格写的,,就当作线段树单点更新的模板吧....(当年用树状数组做的:代码见这里) */ 1 #include < ...
- 【HDU - 1166】敌兵布阵 (线段树模板 单点更新+ 区间查询)
题干: C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务就是要监视这些工兵营地的活动情 ...
- hdu 1754 I Hate It(线段树之 单点更新+区间最值)
I Hate It Time Limit: 90 ...
- Codeforces Beta Round #75 (Div. 1 Only) B. Queue 线段树。单点更新
http://codeforces.com/problemset/problem/91/B 题意: 给你n个数,求得i 到n中小于a[i]的最右边的a[j],然后求a[i]到a[j]之间包含了多少个数 ...
- HUD2795 线段树(单点更新)
题目中给出的h和w范围均大,其实n的最大范围才200000,所以我们建立的线段树大小为min(h,n),线段树的每一个节点包含一个变量c,记录当前区间内还剩下的可以put on的最大长度.插入一个数时 ...
最新文章
- rman备份脚本shell版
- 基于注册中心的Dubbo服务
- IDM出现输入用户名和密码不能下载解决方法
- 服务器装系统提示获取分区失败,u盘安装系统分区错误解决方法
- NSDictionary和NSMutableDictionary
- 【WinForm】自己写一个截图软件1 --注册全局热键
- 火狐可以使用广告终结者_使用Jupyter从终结者终止的地方重新启动脚本
- 计算机考试excel基础试题,计算机基础(Excel2010)试题及答案解析
- html5怎么把图片置顶,html/css如何让图片上下居中(居中垂直)?
- C#集成FastReport.Net并将模板保存到数据库
- Ubuntu 查看系统版本
- 数仓1.4 |业务数仓搭建| 拉链表| Presto
- win7网络不显示共享计算机,win7查找不到网络计算机怎么办_win7看不到网络计算机怎么解决-win7之家...
- 如何使用传统图像处理方法进行大米的计数和长轴方向标记
- 软件学院“SIdea”软件创意大赛
- 微价值:专访个人开发者800万用户之《系统清道夫》
- 最简单的基于FFmpeg的解码器-纯净版(不包含libavformat)
- Laradock 使用笔记
- jquery禁用右键、文本选择功能、复制的代码
- Say Hello to Integers(10分)
热门文章
- windows 找不到本地配置文件用临时配置文件让您登录
- matplotlib.pyplot
- Java学习总结(随笔)——利用JSON解析实现网络下载
- 为激励女工程师推出的编程盛宴
- Espcms 注册或登录提示Can not connect to MySQL server
- Scrum 大白话总结
- 压缩文本、字节或者文件的压缩辅助类-GZipHelper 欢迎收藏
- 使用Aop管理所有Valid结构bindingResult
- 一个新基民的感叹:人心不足蛇吞象
- oracle 删除已备份归档,通过RMAN联机全库备份,包括控制文件,归档日志文件,备份成功后,删除已备份的归档日志。...