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 这个题求最小逆序数,先建一个空的树,然后每输入一个值,就先查询一下,查询之后,更新线段树,然后遍历一遍,每次将第一个数放到最后之后,减 ...
随机推荐
- linux命令行下执行循环动作
在当前子目录下分别创建x86_64 for dir in `ls `;do (cd $dir;mkdir x86_64);done
- HISAT,sTRINGTIE,ballgown三款RNA-seq信息分析软件
HISAT,sTRINGTIE,ballgown三款RNA-seq信息分析软件 2015年04月02日 11:35:47 夜丘 阅读数:8940 标签: 生物 更多 个人分类: 论文笔记 Bowt ...
- CH#56C 异象石
一道LCA 原题链接 先跑一边\(dfs\),求出每个节点的时间戳,如果我们将有异象石的节点按时间戳从小到大的顺序排列,累加相邻两节点之间的距离(首尾相邻),会发现总和就是答案的两倍. 于是我们只需要 ...
- tmux 快捷操作
-- 基本使用 tmux # 运行 tmux -2 以256终端运行 C-b d # 返回主 shell , tmux 依旧在后台运行,里面的命令也保持运行状态 tmux ls # 显示已有tm ...
- UI设计教程分享:设计一个高质量的logo要从哪方面入手呢?
有的人觉得logo只是一个简单的图形,对品牌影响无关紧要:但有的人却觉得logo对品牌有较大的影响.其实logo承载着一个公司的品牌形象.公司背景.公司理念等.就像Landor往往给一个企业做logo ...
- Servlet封装类
Servlet 提供了四个封装类: public class ServletRequestWrapper extends java.lang.Object implements ServletRequ ...
- Data Dictionary 数据字典
数据字典是一种通用的程序设计方法.可以认为,不论什么程序,都是为了处理一定的主体,这里的主体可能是人员.商品(超子).网页.接口.数据库表.甚至需求分析等等.当主体有很多的属性,每种属性有很多的取值, ...
- C++ Crypto++ RSA加密资料收集
C++利用Crypto++,vs2005环境下的RSA应用 基于Crypto++/Cryptopp的rsa密钥生成,rsa加密.解密,rsa签名.验签 Keys and Formats 使用Crypt ...
- eclipse项目两个红点
Description Resource Path Location Type Unbound classpath container: 'JRE Sy 选中项目右键build path 选择libr ...
- this高级应用 - 域隔离
在js环境中,this有很多指向(window.dom.object等),巧妙的利用this,可以有效的防止变量或方法被外界污染,保证代码健壮性,实例如下. demo: <!DOCTYPE ht ...