区间更新POJ3468 HDU1698
来源:互联网 发布:2017网络吉他大赛 编辑:程序博客网 时间:2024/05/08 18:30
网址https://vjudge.net/problem/POJ-3468
最近学了线段树,搞了一下区间更新。模板题吧。
写一下自己需要记住的点吧。
1.空间要为节点数的4倍,我在网上找了一下,大概意思是这样
建树后可能出现这种情况(图片来自http://scinart.github.io/acm/2014/03/19/acm-segment-tree-space-analysis/)
结果在最下面的一行原本没完全使用却占用了空间,占用的是比这个图刚刚大的完美二叉树空间。
计算一下此图空间:((n-1)*2-1+1)*2-1=4n-5
n-1倒数第二行空间。*2-1,,除去最后一行的总空间,,+1最后一行空间。
2.类型要为long long int 类型,因为最后会超int范围
3.被标记的点已经更新完信息。等待向下更新标记。
4.延迟标记。
思想:对于要更新的区段,将其记录在祖先节点,而不完全将祖先节点记录整个区间
的子孙节点信息更新。当需要使用其下的子孙节点时再向下更新信息。这种方式大大减少了
时间复杂度。
方式:修改与查询时,遇到节点,查看其是否被标记。是的话就向下传递标记,更新子节点信息,并消除父节点标记。
5.建立的图如下。。。(好丑)
6.具体地方在里面备注
#include<iostream>#include<cstdio>#include<algorithm>using namespace std;/******************************************************/#define LL long long int#define mem(a,b) memset(a,b,sizeof(a))#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define L rt<<1#define R rt<<1|1#define N 100000+9#define pow(a) a*a#define INF 0x3f3f3f3f#define max(a,b) (a>b?a:b)#define min(a,b) (a<b?a:b)/*********************************************************/LL n, q;LL dat[N<<2];LL sum[N<<2];LL addmark[N<<2];void pushup(LL rt){ sum[rt] = sum[L] + sum[R];}void pushdown(LL rt, LL len){ if (addmark[rt]) { addmark[L] += addmark[rt]; addmark[R] += addmark[rt]; sum[L] += addmark[rt]*(len - (len>>1));//这里要用rt,不用L。加更改后的值 sum[R] += addmark[rt]*(len>>1); addmark[rt] = 0; }}void build(LL l, LL r, LL rt){ addmark[rt] = 0; if (l == r){ scanf("%lld", &sum[rt]); return; } LL m = (l + r) / 2; build(lson); build(rson); pushup(rt);}LL query(LL a,LL b,LL l, LL r, LL rt){ if (a <= l&&r <= b){ return sum[rt]; } LL m = (l + r) / 2; LL res = 0; pushdown(rt, r - l + 1); if (a <= m)res+=query(a, b, lson); if (b>m)res+=query(a, b, rson); return res;}void update(LL a, LL b, LL l, LL r, LL rt, LL c){ if (a <= l&&r <= b){ addmark[rt] += c; sum[rt] += c * (r - l + 1); return; } pushdown(rt, r-l+1); //向下传递标记,更新左右儿子信息 LL m = (l + r) / 2; if(a<=m)update(a, b, lson, c); if(b>m)update(a, b, rson, c); pushup(rt); //向上更新}int main(){ while (~scanf("%lld%lld", &n, &q)) { build(1, n, 1); while (q--){ char s[2]; scanf("%s", s); if (s[0] == 'Q'){ LL a, b; scanf("%lld%lld", &a, &b); LL res = query(a, b, 1, n, 1); printf("%lld\n", res); } else{ LL a, b, c; scanf("%lld%lld%lld", &a, &b, &c); update(a, b, 1, n, 1, c); } } }}
HDU1689区间更新
更新的时候,从顶节点一路往下推。当遇到标记时,将标记向下传递。因为在某区间段更新是在递归最后实现的,所以之前的传递造成的标记会被更新的标记覆盖。更新结束之后,要实现求和的功能。
求和过程也是一路从上往下找。当遇到有标记的节点时,就返回标记的值*区间长度,即该区间的总和。当搜寻到叶子节点,即l==r时,如果有标记,返回标记,没有则返回1(初始值为1,不曾改变)
#include<iostream>#include<cstdio>#include<algorithm>#include<cmath>using namespace std;/******************************************************/#define LL long long int#define mem(a,b) memset(a,b,sizeof(a))#define m ((l+r)/2)#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define L rt<<1#define R rt<<1|1#define N 100000+1#define pow(a) a*a#define INF 0x3f3f3f3f#define max(a,b) (a>b?a:b)#define min(a,b) (a<b?a:b)/*********************************************************//*11021 5 25 9 3*/LL t, n, q;LL addmark[N<<2];void pushdown(LL rt){ if (addmark[rt]) { addmark[L] = addmark[rt]; addmark[R] = addmark[rt]; addmark[rt] = 0; }}void update(LL a, LL b, LL c, LL l, LL r, LL rt){ if (a<=l&&r<=b){ addmark[rt] = c; return; } pushdown(rt); if (a <= m)update(a, b, c, lson); if (b > m)update(a, b, c, rson);}LL add(LL l, LL r, LL rt){ if (addmark[rt]){ return addmark[rt] * (r - l + 1); } if (l == r){ if (addmark[rt]) return addmark[rt]; else return 1; } LL res = 0; res+=add(lson); res+=add(rson); return res;}int main(){ cin >> t; LL cnt = 1; while (t--){ mem(addmark, 0); scanf("%lld%lld", &n, &q); while (q--){ LL a, b, c; scanf("%lld%lld%lld", &a, &b, &c); update(a, b, c, 1, n, 1); } printf("Case %lld: The total value of the hook is %lld.\n",cnt++, add(1, n, 1)); }}
- 区间更新POJ3468 HDU1698
- 【HDU1556】【POJ3468】区间更新
- poj3468(区间更新)
- poj3468 区间更新,区间查询
- HDU1698线段树区间更新
- hdu1698 线段树区间更新
- hdu1698 线段树 区间更新
- HDU1698线段树区间更新
- hdu1698(线段树区间更新)
- 线段树区间更新hdu1698
- hdu1698 线段树区间更新
- HDU1698 线段树 区间更新
- 线段树区间更新poj3468
- poj3468(区间更新->记录增量)
- poj3468线段树区间更新
- POJ3468线段树区间更新
- 树状数组 区间更新 POJ3468
- POJ3468 线段树 区间更新
- iOS学习笔记-038.UITableView示例二——九宫格
- [JNI]开发实例(1)封装libjpeg库 保证图片质量压缩图片
- 论文Convolutional Naural Networks for Sentence Classification--模型介绍篇
- 非微信官方网页,继续访问将转换成手机预览模式
- 蛇行矩阵
- 区间更新POJ3468 HDU1698
- JS获取表单数据
- 阅读Object类源码
- Python基础语法(4)——GUI编程及猜数字游戏
- 2017.3.4 wyd测试
- bzoj 1660 单调栈
- Mount挂载详解
- 2017-03-04 HDU1426 Sudoku Killer
- Java----流程控制语句