HDU 4348To the moon 主席树 + 区间更新
来源:互联网 发布:嘉兴微知电子有限公司 编辑:程序博客网 时间:2024/06/06 03:50
题目:http://acm.hdu.edu.cn/showproblem.php?pid=4348
题意:给定长度为n的数组,有四种操作:C l r d把[l, r]内的元素全部加上d并把时间计数器加1,Q l r查询[l, r]内元素的和,H l r t查询t时刻[l, r]内元素的和,B t返回时刻t(保证只向前而不向后跳)
思路:跳回之前的某个状态,明显是可持久化数据结构,这题就是明显的主席树。此题中区间更新必须lazy操作,不然新建的节点太多必定内存爆炸。如果像普通线段树那样lazy操作还是会内存爆炸,因此要换一种方式:我们用一个标记记录当前区间的累加和,查询时从根节点走到目标节点的过程中不断累加所经过节点的标记值
总结:主席树区间更新和普通线段树区间更新还是不一样的,如果像普通线段树那样,每次需要新建(r - l + 1)log(n)个节点,肯定不行,只能另取它法
#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>using namespace std;typedef long long ll;const int N = 200010;int root[N], lson[N*20], rson[N*20];ll sum[N*20], mark[N*20];int a[N];int n, m, tot;void push_up(int rt){ sum[rt] = sum[lson[rt]] + sum[rson[rt]];}void build(int l, int r, int &rt) //建树{ rt = ++tot; sum[rt] = mark[rt] = 0; if(l == r) { sum[rt] = a[l]; return; } int mid = (l + r) >> 1; build(l, mid, lson[rt]); build(mid + 1, r, rson[rt]); push_up(rt);}void update(int pre, int &rt, int x, int y, int l, int r, int c){ rt = ++tot; lson[rt] = lson[pre], rson[rt] = rson[pre], mark[rt] = mark[pre]; sum[rt] = sum[pre] + (ll)(y - x + 1) * c; //所管辖区间的和 if(l == x && r == y) //记录此区间被累加的和 { mark[rt] += c; return; } int mid = (l + r) >> 1; if(y <= mid) update(lson[pre], lson[rt], x, y, l, mid, c); else if(x > mid) update(rson[pre], rson[rt], x, y, mid + 1, r, c); else { update(lson[pre], lson[rt], x, mid, l, mid, c); update(rson[pre], rson[rt], mid + 1, y, mid + 1, r, c); }}ll query(int x, int y, int l, int r, int rt){ ll ans = (ll)(y - x + 1) * mark[rt]; //不断累加所经过节点的标记值 if(l == x && y == r) return sum[rt]; int mid = (l + r) >> 1; if(y <= mid) ans += query(x, y, l, mid, lson[rt]); else if(x > mid) ans += query(x, y, mid + 1, r, rson[rt]); else { ans += query(x, mid, l, mid, lson[rt]); ans += query(mid + 1, y, mid + 1, r, rson[rt]); } return ans;}int main(){ while(~ scanf("%d%d", &n, &m)) { tot = 0; for(int i = 1; i <= n; i++) scanf("%d", &a[i]); build(1, n, root[0]); char ch; int v, u, c, cnt = 0; for(int i = 1; i <= m; i++) { scanf(" %c%d", &ch, &v); if(ch == 'C') { scanf("%d%d", &u, &c); update(root[cnt], root[cnt+1], v, u, 1, n, c); cnt++; } else if(ch == 'Q') { scanf("%d", &u); printf("%I64d\n", query(v, u, 1, n, root[cnt])); } else if(ch == 'H') { scanf("%d%d", &u, &c); printf("%I64d\n", query(v, u, 1, n, root[c])); } else if(ch == 'B') { cnt = v; tot = root[cnt+1]; } } } return 0;}
0 0
- HDU 4348 To the moon(主席树区间更新)
- hdu-4348-To the moon-主席树在线区间更新
- HDU 4348To the moon 主席树 + 区间更新
- HDU 4348 To the moon 【主席树+区间修改】
- HDU 4348 To the moon [主席树 区间修改]
- hdu-4348-To the moon-离线处理 or 主席树区间更新
- hdu 4348 To the moon(主席树,区间更新节省内存,经典)
- hdu-4348-To the moon(主席树更新,区间更新,区间和查询,保存历史版本返回)
- hdu 4348 To the moon (主席树)
- HDU-4348 To the moon (主席树)
- HDU 4348 To the moon 主席树成段更新
- HDU 4348 / SPOJ TTM To the moon [主席树]
- HDU-4348 To the moon(主席树)
- SPOJ TTM To The Moon 主席树的区间更新与查询
- SPOJ TTM To the moon(主席树+区间操作)
- vjudge: spoj--to the moon(主席树区间修改)
- 【HDU4348】To The Moon-主席树(可持久化线段树)区间修改+区间询问
- hdu4348 To the moon(区间修改,区间查询的主席树)
- 深度学习读书笔记之RBM(限制波尔兹曼机)
- java线程池系列(1)-ThreadPoolExecutor实现原理
- hibernate3.3.2学习笔记---多对多双向
- 为什么要用smarty模板引擎
- EventBus上车指南
- HDU 4348To the moon 主席树 + 区间更新
- ajax跨页面提交表单
- nginx1.10.1学习笔记
- 基本分页、请求分页储存管理方式
- xargs的原理剖析及用法详解
- 集合类浅谈(1)
- 简易mvc框架配置类和日志类的简单实现
- js继承的实现
- 1095. Cars on Campus