社区讨论

为什么我的线段树空间要开八倍才能通过?

学术版参与者 5已保存回复 7

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
6 条
当前快照
1 份
快照标识符
@mkgy8798
此快照首次捕获于
2026/01/16 22:03
上个月
此快照最后确认于
2026/01/19 14:10
上个月
查看原帖

为什么我的线段树空间要开八倍才能通过?

代码:
CPP
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int n, m;
long long a[N];
struct node {
	int l, r;
	long long w, tag;
}tr[N << 3];
void pushup (int u) {
	tr[u].w = tr[u << 1].w + tr[u << 1 | 1].w;
}
void pushtag (int u, long long x, int lng) {
	tr[u].tag += x;
	tr[u].w += x * lng;
}
void pushdown (int u) {
	int l = tr[u].l, r = tr[u].r, mid = l + r >> 1;
	pushtag (u << 1, tr[u].tag, mid - l + 1);
	pushtag (u << 1 | 1, tr[u].tag, r - mid);
	tr[u].tag = 0;
}
void mktr (int u, int l, int r) {
	tr[u].l = l, tr[u].r = r;
	if (l == r) { tr[u].w = a[l]; return; }
	int mid = l + r >> 1;
	mktr (u << 1, l, mid); mktr (u << 1 | 1, mid + 1, r);
	pushup (u);
}
long long query (int x, int y, int u) {
	int l = tr[u].l, r = tr[u].r;
	if (l > y || r < x) return 0;
	pushdown (u);
	if (l >= x && r <= y) return tr[u].w;
	return query (x, y, u << 1) + query (x, y, u << 1 | 1);
}
void add (int x, int y, int u, long long k) {
	int l = tr[u].l, r = tr[u].r;
	if (l > y || r < x) return;
	pushdown (u);
	if (l >= x && r <= y) {
		pushtag (u, k, r - l + 1);
		return;
	}
	add (x, y, u << 1, k); add (x, y, u << 1 | 1, k);
	pushup (u);
}
int main () {
//	return 114514;
	scanf ("%d %d", &n, &m);
	for (int i = 1; i <= n; i++) {
		scanf ("%lld", a + i);
	}
	mktr (1, 1, n);
	while (m--) {
		int o, x, y;
		scanf ("%d %d %d", &o, &x, &y);
		if (o == 1) {
			long long k;
			scanf ("%lld", &k);
			add (x, y, 1, k);
		}
		else {
			printf ("%lld\n", query (x, y, 1));
		}
	}
	return 0;
}
如果这份代码树的空间改成 4n4n 的话会 RE 掉。
之前写的代码却能直接 AC:
CPP
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n, m, x, y;
long long tr[N << 2], lzy[N << 2], a[N], k;
void tag (int u, long long x, int len) {
	tr[u] += x * len;
	lzy[u] += x;
}
void pushup (int u){
	tr[u] = tr[u << 1] + tr[u << 1 | 1];
}
void pushdown (int l, int r, int u){
	int m = l + r >> 1;
	tag (u << 1, lzy[u], m - l + 1);
	tag (u << 1 | 1, lzy[u], r - m);
	lzy[u]=0;
}
void mktr (int l, int r, int u){
	if (l == r) {tr[u] = a[l]; return;}
	int m = l + r >> 1;
	mktr (l, m, u << 1); 
	mktr (m + 1, r, u << 1 | 1);
	pushup (u);
}
bool in (int l, int r) {
	return l >= x && r <= y;
}
bool mgx (int l, int r) {
	return x > r || l > y;
}
long long sum (int u, int l, int r) {
	if (in (l, r)) return tr[u];
	if (mgx (l, r)) return 0;
	pushdown (l, r, u);
	int m = l + r >> 1;
	return sum (u << 1, l, m) + sum (u << 1 | 1, m + 1 , r);
}
void jia (int u, int l, int r){
	if (in (l, r)){
		tag (u, k, r - l + 1);
	}
	else if (!mgx (l, r)){
		pushdown (l, r, u);
		int m = l + r >> 1;
		jia (u << 1, l, m); jia (u << 1 | 1, m + 1, r);
		pushup (u); 
	}
}
int main () {
	scanf ("%d %d", &n, &m);
	for (int i = 1; i <= n; i++)
		scanf ("%lld", &a[i]);
	mktr (1, n, 1);
	while (m--) {
		int o;
		scanf ("%d %d %d", &o, &x, &y);
		if (o == 1) {
			scanf ("%lld", &k);
			jia (1, 1, n);
		}
		else printf ("%lld\n", sum (1, 1, n));
	}
	return 0;
}
呜呜呜,我之前闲着翻讨论区的时候看到别人问这个问题的,奈何没仔细看,没想到同样的问题又发生到我身上了。

回复

7 条回复,欢迎继续交流。

正在加载回复...