HDU 4893 线段树的 点更新 区间求和
Wow! Such Sequence!
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 2067 Accepted Submission(s): 619
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.
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.
2 1 1
5 4
1 1 7
1 3 17
3 2 4
2 1 5
22
题意:
题目中说对一个长度为n,初始元素都为0的数组进行三种操作,如下:
1 k d 第 k 个元素加上 d
2 l r 求从 l 到 r 所有元素的和
3 l r 改变从 l 到 r 所有元素,都为原元素最近的 Fibonacci 数,差值相等时取较小值
思路:
对于第一个操作需要用到线段树中的单点更新操作,对于第二个操作需要用到线段树中的区
间求和操作,对于第三个操作需要思考一下,怎么处理才能最快地改变我们需要改变区间的状态。因为对于区间有个求和操作,那么我们会考虑到只需要改变一段区
间的和即可。处理的方案就是提前对每一段的 区间和 都找到相应的 Fibonacci 数作为映射,那么我们要对区间进行第三操作时,只需要将区间做一下标记,然后将这个映射值覆盖到原
区间和 即可。
注意点:
1.注意 pushdown 和 pushup 的使用。
2.注意当访问到叶子节点时最好是返回(return),若不返回那么开大线段树的大小(原为4倍)也行。
3.注意杭电的输出为 %I64。
#include <cstdio>
#include <cmath>
using namespace std;
#define N 100010 struct node {
int L, R;
long long sum, vsum;
int flag;
} tree[N << ];
long long ans; long long ffib(long long val) {
long long x = , y = ;
int i;
for (i = ; i < ; ++i) {
y = x + y;
x = y - x;
if(y >= val)
break;
}
if(fabs(y - val) < fabs(x - val))
return y;
return x;
} void pushUp(int root) { ///向上回溯 不断更新区间和
if(tree[root].L == tree[root].R) return;
tree[root].sum = tree[root << ].sum + tree[root << | ].sum;
tree[root].vsum = tree[root << ].vsum + tree[root << | ].vsum;
} void pushDown(int root) { ///向下更新 falg==1更新的时候
if(tree[root].flag && tree[root].L == tree[root].R) {
tree[root].sum = tree[root].vsum; ///.vsum 求和之后对应该点的Fri数
tree[root].flag = ; ///遍历完了
return ;
}
if(tree[root].flag) {
tree[root << ].flag = tree[root << | ].flag = ;
tree[root << ].sum = tree[root << ].vsum;
tree[root << | ].sum = tree[root << | ].vsum;
tree[root].flag = ; ///遍历完了
}
} void build(int L, int R, int root) { ///建树
tree[root].L = L;
tree[root].R = R;
tree[root].flag = ;
if(L == R) {
tree[root].sum = ;
tree[root].vsum = ;
return ;
}
int mid = (L + R) >> ;
build(L, mid, root << );
build(mid + , R, root << | );
pushUp(root); ///递归遍历求和
} void add(int pos, int val, int root) {
if (tree[root].L == tree[root].R) {
tree[root].sum += val;
tree[root].vsum = ffib(tree[root].sum);
tree[root].flag = ;
return ;
}
pushDown(root);
int mid = (tree[root].L + tree[root].R) >> ;
if (mid >= pos) add(pos, val, root << );
else add(pos, val, root << | );
pushUp(root);
} void update(int L, int R, int root) {
if (L <= tree[root].L && R >= tree[root].R) {
tree[root].flag = ;
tree[root].sum = tree[root].vsum;
return ;
}
pushDown(root);
int mid = (tree[root].L + tree[root].R) >> ;
if (mid >= R) update(L, R, root << );
else if (mid + <= L) update(L, R, root << | );
else {
update(L, mid, root << );
update(mid + , R, root << | );
}
pushUp(root);
} void query(int L, int R, int root) {
if (L <= tree[root].L && R >= tree[root].R) {
ans += tree[root].sum;
return ;
}
pushDown(root);
int mid = (tree[root].L + tree[root].R) >> ;
if (mid >= R) query(L, R, root << );
else if (mid + <= L) query(L, R, root << | );
else {
query(L, mid, root << );
query(mid + , R, root << | );
}
pushUp(root);
} int main(int argc, char *argv[]) {
int n, m, i;
int op, x, y;
while(scanf("%d%d", &n, &m) != EOF) {
build(, n, );
for (i = ; i < m; ++i) {
scanf("%d%d%d", &op, &x, &y);
if(op == ) {
add(x, y, );
} else if(op == ) {
ans = ;
query(x, y, );
printf("%I64d\n", ans); // hdu
} else if(op == ) {
update(x, y, );
}
}
}
return ;
}
http://wenku.baidu.com/link?url=Hk-fzFeInk-_Huvwf7CVVQav0XcEmRn7CEIHNraqHpOYWgJrYXpDEmcRxrzkoB9zs5Xx3A_o7Sk3n9Z2IDyPCWeRHINEgiiu4MFNQ98CIqG
HDU 4893 线段树的 点更新 区间求和的更多相关文章
- HDU 1166 敌兵布阵(线段树单节点更新 区间求和)
http://acm.hdu.edu.cn/showproblem.php?pid=1166 Problem Description C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Dere ...
- hdu 1166 线段树(单点增减 区间求和)
Sample Input1101 2 3 4 5 6 7 8 9 10Query 1 3Add 3 6Query 2 7Sub 10 2Add 6 3Query 3 10End Sample Outp ...
- HDU 3577 Fast Arrangement ( 线段树 成段更新 区间最值 区间最大覆盖次数 )
线段树成段更新+区间最值. 注意某人的乘车区间是[a, b-1],因为他在b站就下车了. #include <cstdio> #include <cstring> #inclu ...
- POJ 3468 A Simple Problem with Integers(线段树 成段增减+区间求和)
A Simple Problem with Integers [题目链接]A Simple Problem with Integers [题目类型]线段树 成段增减+区间求和 &题解: 线段树 ...
- HDU 1754 I Hate It(线段树之单点更新 区间最值查询)
I Hate It Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total S ...
- hdu 1754 I Hate It(线段树之 单点更新+区间最值)
I Hate It Time Limit: 90 ...
- HDU - 1754 线段树-单点修改+询问区间最大值
这个也是线段树的经验问题,待修改的,动态询问区间的最大值,只需要每次更新的时候,去把利用子节点的信息进行修改即可以. 注意更新的时候区间的选择,需要对区间进行二分. #include<iostr ...
- hdu 1754 线段树(单点替换 区间最值)
Sample Input5 61 2 3 4 5Q 1 5 //1-5结点的最大值U 3 6 //将点3的数值换成6Q 3 4Q 4 5U 2 9Q 1 5 Sample Output5659 # i ...
- HDU 1394.Minimum Inversion Number-最小逆序数-完全版线段树(单点增减、区间求和)
HDU1394.Minimum Inversion Number 这个题求最小逆序数,先建一个空的树,然后每输入一个值,就先查询一下,查询之后,更新线段树,然后遍历一遍,每次将第一个数放到最后之后,减 ...
随机推荐
- fastcgi协议解析(nginx)
请求NGINX ->[ {(post data) +> (NGX_HTTP_FASTCGI_STDIN)} * N +> {(environment variables) +> ...
- IOS初级:SDWebImage
简单用法 #import "ViewController.h" #import "SDWebImage/UIImageView+WebCache.h" @int ...
- centos6.5上配置apache + mysql + php4.4.9 + eaccelerator-0.9.5 + postgresql-8.3.13 备忘
1.apache + mysql 直接利用 yum 安装 yum -y install httpd httpd-devel mysql mysql-server httpd-manual mod_pe ...
- mybatis缓存(一,二级别)
数据查找过程: 二级缓存(默认关闭) -> 一级缓存(默认开启) -> 数据库 一级缓存: 一级缓存是SqlSession自带的.SqlSession对象被创建,一级缓存就存在了.//是针 ...
- 微信小程序开发工具常用快捷键
格式调整 Ctrl+S:保存文件 Ctrl+[, Ctrl+]:代码行缩进 Ctrl+Shift+[, Ctrl+Shift+]:折叠打开代码块 Ctrl+C Ctrl+V:复制粘贴,如果没有选中任何 ...
- ManageEngine卓豪 IT管理峰会圆满结束
- thymeleaf使用基础教程
thymeleaf 是新一代的模板引擎,在spring4.0中推荐使用thymeleaf来做前端模版引擎. thymeleaf介绍 简单说, Thymeleaf 是一个跟 Velocity.FreeM ...
- 2018.12.18 bzoj5296: [Cqoi2018]破解D-H协议(bsgs)
传送门 bsgsbsgsbsgs基础题. 考虑到给的是原根,因此没无解的情况. 于是只需要每次把a,ba,ba,b解出来. 然后可以通过预处理节省一部分时间. 代码: #include<bits ...
- 2018.12.17 hdu2138 How many prime numbers(miller-rbin)
传送门 miller−rabbinmiller-rabbinmiller−rabbin素数测试的模板题. 实际上miller−rabinmiller-rabinmiller−rabin就是利用费马小定 ...
- idea设置字体大小
第一次玩儿idea,也是个新手小白,甚是惭愧,也是一步步慢慢摸索,下面我们按照步骤一步步操作 就可以了. 1.首先,先设置代码的字体大小: 2.设置周围菜单栏的字体大小: 3.设置控制台的字体大小: