小阳的贝壳
这里最难维护的应该是区间了,但是我们有一个结论,所以这一步可以转换为维护整个序列的差分。
对于操作一:我们只要对端点的值增加,对端点的值减小。
对于操作二:我们只要得到差分数组里的绝对值最大值就行了。
对于操作三:我们首先要得到,然后得到这一段差分序列的,然后再于求一个即为答案。
对一整颗线段树我们只要维护三个值:区间、区间绝对值最大、区间和,我们就可以完成上面的三个操作了。
然后对某些线段树上的操作特判防止数组越界即可。
#include <bits/stdc++.h> #define mid (l + r >> 1) #define lson rt << 1, l, mid #define rson rt << 1 | 1, mid + 1, r #define ls rt << 1 #define rs rt << 1 | 1 using namespace std; typedef long long ll; const int N = 1e5 + 10; ll maxn[N << 2], gd[N << 2], sum[N << 2], a[N]; void push_up(int rt) { sum[rt] = sum[ls] + sum[rs]; gd[rt] = __gcd(gd[ls], gd[rs]); maxn[rt] = max(maxn[ls], maxn[rs]); } void build(int rt, int l, int r) { if (l == r) { gd[rt] = abs(a[l]); maxn[rt] = abs(a[l]); sum[rt] = a[l]; return ; } build(lson); build(rson); push_up(rt); } void update(int rt, int l, int r, int L, int R, int x) { if (l >= L && r <= R) { sum[rt] += x; gd[rt] = abs(sum[rt]); maxn[rt] = abs(sum[rt]); return ; } if (L <= mid) update(lson, L, R, x); if (R > mid) update(rson, L, R, x); push_up(rt); } ll query_max(int rt, int l, int r, int L, int R) { if (l >= L && r <= R) { return maxn[rt]; } ll ans = 0; if (L <= mid) ans = max(ans, query_max(lson, L, R)); if (R > mid) ans = max(ans, query_max(rson, L, R)); return ans; } ll query_sum(int rt, int l, int r, int L, int R) { if (l >= L && r <= R) { return sum[rt]; } ll ans = 0; if (L <= mid) ans += query_sum(lson, L, R); if (R > mid) ans += query_sum(rson, L, R); return ans; } ll query_gcd(int rt, int l, int r, int L, int R) { if (l >= L && r <= R) { return gd[rt]; } ll ans = 0; if (L <= mid) ans = __gcd(ans, query_gcd(lson, L, R)); if (R > mid) ans = __gcd(ans, query_gcd(rson, L, R)); return ans; } int main() { // freopen("in.txt", "r", stdin); // freopen("out.txt", "w", stdout); ios::sync_with_stdio(false), cin.tie(0), cout.tie(0); int n, m; cin >> n >> m; for (int i = 1; i <= n; i++) { cin >> a[i]; } for (int i = n; i >= 1; i--) { a[i] -= a[i - 1]; } build(1, 1, n); for (int i = 1; i <= m; i++) { int op, l, r, x; cin >> op >> l >> r; if (op == 1) { cin >> x; update(1, 1, n, l, l, x); if (r + 1 <= n) { update(1, 1, n, r + 1, r + 1, -x); } } else if (op == 2) { if (l == r) { cout << "0\n"; } else { cout << query_max(1, 1, n, l + 1, r) << "\n"; } } else { if (l == r) { cout << query_sum(1, 1, n, 1, r) << "\n"; } else { ll cur = query_sum(1, 1, n, 1, l); cout << __gcd(cur, query_gcd(1, 1, n, l + 1, r)) << "\n"; } } } return 0; }