区间更新 区间和查询 带有延迟标记 线段树 hdu1698; 附:csa 区间加值,维护最大值
2017-07-11 13:59
615 查看
hdu1698
不知怎么搞的,1s内提交了两次。
![](http://img.blog.csdn.net/20170711135935409)
poj3468
成段更新(通常这对初学者来说是一道坎),需要用到延迟标记(或者说懒惰标记),简单来说就是每次更新的时候不要更新到底,用延迟标记使得更新延迟到下次需要更新or询问到的时候
线段树功能:update:成段替换 (由于只query一次总区间,所以可以直接输出1结点的信息)不知怎么搞的,1s内提交了两次。
#define _CRT_SECURE_NO_WARNINGS #include <cstdio> #include <algorithm> #include <cstring> using namespace std; const int N = 1e5 + 7; int segTree[N << 2]; //segTree[i]根为i的区间树的叶子和 int inc[N << 2]; //他们管这叫延迟标记。(其实还有左右孩纸指针,都是节点的一部分,可以写成结构体) inline void pushUp(int rt) { segTree[rt] = segTree[rt << 1] + segTree[rt << 1 | 1]; } inline void pushDown(int rt, int len) { if (inc[rt] != 0) { inc[rt << 1] = inc[rt << 1 | 1] = inc[rt]; segTree[rt << 1] = ((len + 1) >> 1) * inc[rt]; segTree[rt << 1 | 1] = (len >> 1) * inc[rt]; inc[rt] = 0; } } void build(int rt, int l, int r) { inc[rt] = 0; segTree[rt] = 1; if (l == r) return; int mid = l + r >> 1; build(rt << 1, l, mid); build(rt << 1 | 1, mid + 1, r); pushUp(rt); } void update(int rt, int l, int r, int L, int R, int val) { if (L <= l && r <= R) { inc[rt] = val;//延迟标记置为val segTree[rt] = (r - l + 1) * val; return; } pushDown(rt, r - l + 1); //更新时把延迟标记带下去 int mid = l + r >> 1; if (L <= mid) update(rt << 1, l, mid, L, R, val); if (R > mid) update(rt << 1 | 1, mid + 1, r, L, R, val); pushUp(rt); } int main() { int T, kase = 0; scanf("%d", &T); while (T-- > 0) { memset(segTree, 0, sizeof segTree); memset(inc, 0, sizeof inc); int n, m; scanf("%d%d", &n, &m); build(1, 1, n); while(m-- > 0) { int x, y, z; scanf("%d%d%d", &x, &y, &z); update(1, 1, n, x, y, z); } printf("Case %d: The total value of the hook is %d.\n", ++kase, segTree[1]); } return 0; }
poj3468
#define _CRT_SECURE_NO_WARNINGS #include <cstdio> #include <iostream> #include <algorithm> #include <cstring> using namespace std; const int N = 1e5 + 7; int n, m, a ; long long segTree[N << 2], inc[N << 2]; //保存节点所在区间的数字和 void pushUp(int rt) { segTree[rt] = segTree[rt << 1] + segTree[rt << 1 | 1]; } void pushDown(int rt, int len) { inc[rt << 1] += inc[rt]; inc[rt << 1 | 1] += inc[rt]; segTree[rt << 1] += inc[rt] * (len - (len >> 1)); segTree[rt << 1 | 1] += inc[rt] * (len >> 1); inc[rt] = 0; } void build(int rt, int l, int r) { if (l == r) { scanf("%lld", segTree + rt); return; } int mid = l + r >> 1; build(rt << 1, l, mid); build(rt << 1 | 1, mid + 1, r); pushUp(rt); } void update(int rt, int l, int r, int L, int R, int val) { if (L <= l && r <= R) { inc[rt] += val; segTree[rt] += (r - l + 1) * val; return; } pushDown(rt, r - l + 1); int mid = l + r >> 1; if (L <= mid) update(rt << 1, l, mid, L, R, val); if (R > mid) update(rt << 1 | 1, mid + 1, r, L, R, val); pushUp(rt); } long long query(int rt, int l, int r, int L, int R) { if (L <= l && r <= R) return segTree[rt]; pushDown(rt, r - l + 1); int mid = l + r >> 1; long long ret = 0; if (L <= mid) ret += query(rt << 1, l, mid, L, R); if (R > mid) ret += query(rt << 1 | 1, mid + 1, r, L, R); return ret; } int main() { ios::sync_with_stdio(false); cin.tie(0); while (cin >> n >> m) { memset(segTree, 0, sizeof segTree); memset(inc, 0, sizeof inc); build(1, 1, n); while (m-- > 0) { char opt; int x, y, z; scanf(" %c", &opt); if (opt == 'Q') { scanf("%d%d", &x, &y); printf("%lld\n", query(1, 1, n, x, y)); } else if (opt == 'C') { scanf("%d%d%d", &x, &y, &z); update(1, 1, n, x, y, z); } } } return 0; }上一题的结构体写法,结构体要存每个节点的区间范围,肯定是占内存些的。
#include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N = 100000 + 7; struct Tree { int l, r; long long inc, s; }t[N << 2]; void pushUp(int id) { t[id].s = t[id << 1].s + t[id << 1 | 1].s; } void pushDown(int id) { t[id << 1].inc += t[id].inc; t[id << 1 | 1].inc += t[id].inc; t[id << 1].s += (t[id << 1].r - t[id << 1].l + 1) * t[id].inc; t[id << 1 | 1].s += (t[id << 1 | 1].r - t[id << 1 | 1].l + 1) * t[id].inc; t[id].inc = 0; } void build(int id, int l, int r) { t[id].l = l, t[id].r = r; t[id].inc = 0; if (l == r) { cin >> t[id].s; return; } int m = l + r >> 1; build(id << 1, l, m); build(id << 1 | 1, m + 1, r); pushUp(id); } void update(int id, int l, int r, int val) { if (l <= t[id].l && t[id].r <= r) { t[id].inc += val; t[id].s += (t[id].r - t[id].l + 1) * val; return; } pushDown(id); int m = t[id].l + t[id].r >> 1; if (l <= m) update(id << 1, l, r, val); if (r > m) update(id << 1 | 1, l, r, val); pushUp(id); } long long query(int id, int l, int r) { if (l <= t[id].l && t[id].r <= r) return t[id].s; pushDown(id); int m = t[id].l + t[id].r >> 1; long long res = 0; if (l <= m) res += query(id << 1, l, r); if (r > m) res += query(id << 1 | 1, l, r); return res; } int main() { ios::sync_with_stdio(false); int n, m; while (cin >> n >> m) { build(1, 1, n); char opt; int x, y, z; while (m--) { cin >> opt >> x >> y; if (opt == 'Q') cout << query(1, x, y) << endl; else if (opt == 'C') { cin >> z; update(1, x, y, z); } } } return 0; }https://csacademy.com/contest/archive/task/remove-update
#include <cstdio> #include <algorithm> using namespace std; const int N = 1e5 + 7, inf = 1e15; struct Seg { int l, r; long long maxV, val; }t[N << 2]; struct Opt { int l, r; long long x; }opt ; void pushDown(int id) { if(t[id].val != 0) { t[id << 1].val += t[id].val; t[id << 1].maxV += t[id].val; t[id << 1 | 1].val += t[id].val; t[id<<1|1].maxV += t[id].val; t[id].val = 0; } } void pushUp(int id) { t[id].maxV = max(t[id << 1].maxV, t[id << 1 | 1].maxV); } void build(int id, int l, int r) { t[id].l = l, t[id].r = r, t[id].maxV = t[id].val = 0; if(l == r) return; int mid = l + r >> 1; build(id << 1, l, mid); build(id << 1 | 1, mid + 1, r); } void update(int id, int l, int r, int x) { if(l <= t[id].l && t[id].r <= r) { t[id].maxV += x; t[id].val += x; return; } if(t[id].l == t[id].r) {t[id].maxV += t[id].val; t[id].val = 0;return;} pushDown(id); int mid = t[id].l + t[id].r >> 1; if(l <= mid) update(id << 1, l, r, x); if(r > mid) update(id << 1 | 1, l, r, x); pushUp(id); } int main() { int n, m; while(~scanf("%d%d", &n, &m)) { build(1, 1, n); for (int i = 0; i < m; ++i) { scanf("%d%d%lld", &opt[i].l, &opt[i].r, &opt[i].x); update(1, opt[i].l, opt[i].r, opt[i].x); } long long ans = inf; for(int i = 0; i < m; ++i) { update(1, opt[i].l, opt[i].r, -opt[i].x); ans = min(ans, t[1].maxV); update(1, opt[i].l, opt[i].r, opt[i].x); } printf("%lld\n", ans); } return 0; }
相关文章推荐
- hdu1698-Just a Hook (线段树区间更新)(延迟标记)
- poj3468---线段树----区间单点更新、区间和查询----有延迟标记
- hdu1698 Just a Hook 线段树延迟标记区间更新 求加权区间总和
- 线段树专题#4_蒟蒻训练历程记录_HDU1698_ 延迟标记、区间更新
- HDOJ-2795 Billboard [线段树][单点更新+单点查询+维护区间最值]
- 线段树 (区间修改 区间查询 延迟标记)
- 线段树区间更新延迟标记
- hdoj 3397 Sequence operation 【线段树区间覆盖 + 异或 + 合并】【维护延迟标记的顺序】
- HDOJ-2795 Billboard [线段树][单点更新+单点查询+维护区间最值]
- 线段树维护区间最大模板(单结点更新)(1754)
- 线段树区间更新模板(lazy延迟标记)(1698)
- 线段树1(带懒惰标记的区间更新和整棵树的查询)
- 杭电 HDU ACM 1698 Just a Hook(线段树 区间更新 延迟标记)
- HDU 3577 Fast Arrangement(线段树功能:区间更新,查询区间的最大覆盖次数)
- 线段树 单点更新查询 区间最大值 hdu 2795 Billboard
- hdoj 2795 Billboard 【线段树 单点更新 + 维护区间最大值】
- Poj 3468 A Simple Problem with Integers(线段树 区间更新 延迟标记)
- 线段树(区间和,最大值,最小值,区间动态更新查询)
- [线段树]poj3667 Hotel(区间合并、更新、延迟/懒惰标记
- poj3468 A Simple Problem with Integers 线段树延迟标记区间更新区间求和