您的位置:首页 > 运维架构

区间更新 区间和查询 带有延迟标记 线段树 hdu1698; 附:csa 区间加值,维护最大值

2017-07-11 13:59 615 查看
hdu1698

成段更新(通常这对初学者来说是一道坎),需要用到延迟标记(或者说懒惰标记),简单来说就是每次更新的时候不要更新到底,用延迟标记使得更新延迟到下次需要更新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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: