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 这个题求最小逆序数,先建一个空的树,然后每输入一个值,就先查询一下,查询之后,更新线段树,然后遍历一遍,每次将第一个数放到最后之后,减 ...
随机推荐
- Yii2-设置和获取、删除Cookies空值分析(有代码)
Yii2-设置和获取,删除Cookies空值或值没有变化 原因: 1.不要使用相同的request url, 否则需要刷新才能获取值 可在不同的动作中设置和调用 2.不要在函数中使用exit来中止脚本 ...
- qrcode解决方案大全
QRCODE解决方案 1.delphi原生QRCode.pas 2.delphi编写http服务器实现QRcode请求生成图片,http下载 3.delphi编写cgi程序,加载到apache服务器 ...
- java 银联接口开发
http://blog.sina.com.cn/s/blog_6c868c470100ys59.html 在线接口文档:http://wenku.baidu.com/link?url=EUgAuOKz ...
- base64编码是什么1
首先明确一点base64 是一种编码格式.就想UNICODE一样,能在电脑上表示所有字符,或者换句话说通过编码能让电脑理解你想要表示的字符(因为电脑只知道0和1 ) 就像ascII 中 0100 00 ...
- centos php 运行环境搭建
一.安装apache httpd rpm -qa|grep httpd //检查是否安装apache rpm -e 包名 --nodeps //若有则删除 PS:我没有删除,直接用的服务器原来的. y ...
- Java学习笔记:多线程(一)
Java中线程的五种状态: 新建状态(New) 就绪状态(Runnable) 运行状态(Running) 阻塞状态(Blocked) 凋亡状态(Dead) 其中阻塞状态(Blocked)又分为三种: ...
- Struct配置
这里只是写到配置方法: 第一步:LoginAction: package com.inspur.actions; import javax.servlet.http.HttpServletReques ...
- python下使用opencv拍照
首先在命令中安装opencv: pip install opencv-python 然后打开notebook: jupyter notebook 建立文件,写入如下代码: import cv2 cap ...
- kbmmw 5.01 发布
Important notes (changes that may break existing code) ============================================= ...
- html-day04
html-day04 1.html属性的弊端 1.完成相同的功能需要不同的属性支持 2.可维护性不高2.CSS 1.什么是CSS Cascading Style Sheet 层叠样式表.级联样式表.样 ...