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 这个题求最小逆序数,先建一个空的树,然后每输入一个值,就先查询一下,查询之后,更新线段树,然后遍历一遍,每次将第一个数放到最后之后,减 ...
随机推荐
- Oracle Linux下数据库操作的相关问题
1.su - oracle 切换到oracle用户 lsnrctl status 查看数据库监听状态 lsnrctl start 打开数据库监听 2.Connected to an idle inst ...
- java.lang.NoClassDefFoundError: org/apache/ibatis/cursor/Cursor
因为mybatis的版本和mybatis-spring的版本不兼容导致的,解决方法:mybatis的3.4.0及以上版本用mybatis-spring1.3.0及以上版本:mybatis的3.4.0以 ...
- CH#56C 异象石
一道LCA 原题链接 先跑一边\(dfs\),求出每个节点的时间戳,如果我们将有异象石的节点按时间戳从小到大的顺序排列,累加相邻两节点之间的距离(首尾相邻),会发现总和就是答案的两倍. 于是我们只需要 ...
- imaplib.error: command: SEARCH => got more than 10000 bytes
imaplib.error: command: SEARCH => got more than 10000 bytes 使用IMAPLIB进行标记邮件状态的时候,在 typ,data=M.sea ...
- 深入研究 UCenter API For .NET
康盛旗下产品的搭建 来自http://www.dozer.cc/2011/02/ucenter-api-in-depth-4th/ 1.UCenter 这个当然是最基本的东西,安装起来也很简单,官方就 ...
- Linux安装及入门
Linux安装及学习 Linux遇到的问题: 在安装过程中因为代码输错(少空格)而质疑自己下载的ubuntu和virtualbox版本,于是卸载之后重新安装了一次,后来才发现是代码输错了(教程中的空格 ...
- DB2 sql报错后查证原因与解决问题的方法
1.对于执行中的报错,可以在db2命令行下运行命令 : db2=>? SQLxxx 查看对应的报错原因及解决方法. 2.错误SQL0206N SQLSTATE=42703 检测到一个未定义的列 ...
- “matplotlib display text must have all code points < 128 or use Unicode strings”解决方法
import sys reload(sys) sys.setdefaultencoding('utf-8') 插入以上代码,便可解决.
- idea配置springBoot项目热加载
1.在application.properties中禁用模板引擎缓存 比如freemarker:spring.freemarker.cache=false 2.在pom.xml中添加依赖 <de ...
- json(原生态)
什么是 JSON ? JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation) JSON 是轻量级的文本数据交换格式 JSON 独立于语言 * JSO ...