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

70 阅读2分钟

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[N];
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;
}

csacademy.com/contest/arc…

#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[N];
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;
}


\

\