为什么这种写法在此题会RE
查看原帖
为什么这种写法在此题会RE
599540

rt,本人习惯于在线段树节点的结构体中保存区间左端点和右端点,但是这一种做法无法通过此题,会导致RE。而像题解中的做法一样临时计算区间左端点和区间右端点则可以通过。

以下是我习惯的写法,提交后RE:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <ctime>

#define MAXN 105000

using namespace std;
using ll = long long;
using ull = unsigned long long;
using i128 = __int128;

typedef struct {
	ll sum, gcd;
	ll l, r;
} Node;

ll a[MAXN], cf[MAXN];
Node segt[MAXN<<2];

void tbuild(ll rt, ll l, ll r) {
	segt[rt].l = l, segt[rt].r = r;
	if (l == r) {
		segt[rt].sum = cf[l];
		segt[rt].gcd = abs(cf[l]);
		return;
	}
	ll mid = (l + r) >> 1;
	tbuild(rt << 1, l, mid);
	tbuild(rt << 1 | 1, mid + 1, r);
	segt[rt].sum = segt[rt << 1].sum + segt[rt << 1 | 1].sum;
	segt[rt].gcd = __gcd(segt[rt << 1].gcd, segt[rt << 1 | 1].gcd);
	return;
}

ll findgcd(ll rt, ll l, ll r) {
	if (segt[rt].l >= l && segt[rt].r <= r) {
		return segt[rt].gcd;
	}
	ll gcd = 0;
	if (segt[rt << 1].r >= l) {
		gcd = __gcd(gcd, findgcd(rt << 1, l, r));
	}
	if (segt[rt << 1 | 1].l <= r) {
		gcd = __gcd(gcd, findgcd(rt << 1 | 1, l, r));
	}
	return gcd;
}

ll findsum(ll rt, ll l, ll r) {
	if (segt[rt].l >= l && segt[rt].r <= r) {
		return segt[rt].sum;
	}
	ll sum = 0;
	if (segt[rt << 1].r >= l) {
		sum += findsum(rt << 1, l, r);
	}
	if (segt[rt << 1 | 1].l <= r) {
		sum += findsum(rt << 1 | 1, l, r);
	}
	return sum;
}

void pchange(ll rt, ll poi, ll k) {
	if (segt[rt].l == segt[rt].r) {
		segt[rt].sum += k;
		segt[rt].gcd = abs(segt[rt].sum);
		return;
	}
	if (segt[rt << 1].r >= poi) {
		pchange(rt << 1, poi, k);
	} else {
		pchange(rt << 1 | 1, poi, k);
	}
	segt[rt].gcd = __gcd(segt[rt << 1].gcd, segt[rt << 1 | 1].gcd);
	segt[rt].sum = segt[rt << 1].sum + segt[rt << 1 | 1].sum;
	return;
}

int main() {
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	ios::sync_with_stdio(false);
	ll n, m, op, l, r;
	cin >> n;
	for (ll i = 1; i <= n; i++) {
		cin >> a[i];
		cf[i] = a[i] - a[i - 1];
	}
	cin >> m;
	tbuild(1, 1, n);
	for (ll i = 1; i <= m; i++) {
		cin >> op >> l >> r;
		if (!op) {
			cout << __gcd(findsum(1, 1, l), findgcd(1, l + 1, r)) << endl;
		} else {
			pchange(1, l, op);
			if (r < n) {
				pchange(1, r + 1, -op);
			}
		}
	}

	return 0;
}

以下是类似题解的写法,可以AC:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <ctime>

#define MAXN 105000

using namespace std;
using ll = long long;
using ull = unsigned long long;
using i128 = __int128;

typedef struct {
	ll sum, gcd;
} Node;

ll a[MAXN], cf[MAXN];
Node segt[MAXN << 2];

void tbuild(ll rt, ll l, ll r) {
	if (l == r) {
		segt[rt].sum = cf[l];
		segt[rt].gcd = abs(cf[l]);
		return;
	}
	ll mid = (l + r) >> 1;
	tbuild(rt << 1, l, mid);
	tbuild(rt << 1 | 1, mid + 1, r);
	segt[rt].sum = segt[rt << 1].sum + segt[rt << 1 | 1].sum;
	segt[rt].gcd = __gcd(segt[rt << 1].gcd, segt[rt << 1 | 1].gcd);
	return;
}

ll findgcd(ll rt, ll l, ll r, ll rl, ll rr) {
	if (rl >= l && rr <= r) {
		return segt[rt].gcd;
	}
	ll gcd = 0, mid = (rl + rr) >> 1;
	if (mid >= l) {
		gcd = __gcd(gcd, findgcd(rt << 1, l, r, rl, mid));
	}
	if (mid < r) {
		gcd = __gcd(gcd, findgcd(rt << 1 | 1, l, r, mid + 1, rr));
	}
	return gcd;
}

ll findsum(ll rt, ll l, ll r, ll rl, ll rr) {
	if (rl >= l && rr <= r) {
		return segt[rt].sum;
	}
	ll sum = 0, mid = (rl + rr) >> 1;
	if (mid >= l) {
		sum += findsum(rt << 1, l, r, rl, mid);
	}
	if (mid < r) {
		sum += findsum(rt << 1 | 1, l, r, mid + 1, rr);
	}
	return sum;
}

void pchange(ll rt, ll poi, ll k, ll rl, ll rr) {
	if (rl == rr) {
		segt[rt].sum += k;
		segt[rt].gcd = abs(segt[rt].sum);
		return;
	}
	ll mid = (rl + rr) >> 1;
	if (mid >= poi) {
		pchange(rt << 1, poi, k, rl, mid);
	} else {
		pchange(rt << 1 | 1, poi, k, mid + 1, rr);
	}
	segt[rt].gcd = __gcd(segt[rt << 1].gcd, segt[rt << 1 | 1].gcd);
	segt[rt].sum = segt[rt << 1].sum + segt[rt << 1 | 1].sum;
	return;
}

int main() {
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	ios::sync_with_stdio(false);
	ll n, m, op, l, r;
	cin >> n;
	for (ll i = 1; i <= n; i++) {
		cin >> a[i];
		cf[i] = a[i] - a[i - 1];
	}
	cin >> m;
	tbuild(1, 1, n);
	for (ll i = 1; i <= m; i++) {
		cin >> op >> l >> r;
		if (!op) {
			cout << __gcd(findsum(1, 1, l, 1, n), findgcd(1, l + 1, r, 1, n)) << endl;
		} else {
			pchange(1, l, op, 1, n);
			if (r < n) {
				pchange(1, r + 1, -op, 1, n);
			}
		}
	}

	return 0;
}

为什么第一份代码会RE,第二份不会?求解答/kel

2024/7/4 19:42
加载中...