H、小阳的贝壳
区间增加,区间求差的绝对值的最大值,区间gcd
1、,同理 ,所以维护一个差分数组,求区间和、最大值、最小值、gcd就可以A掉这题。
Code:
#include <bits/stdc++.h>
#define ll long long
#define lson left,mid,k<<1
#define rson mid+1,right,k<<1|1
#define imid int mid=(left+right)/2;
using namespace std;
const int MAXN = 1e5 + 5;
struct node
{
int l;
int r;
ll sum;
ll maxn;
ll minn;
ll gcds;
}que[MAXN * 4];
int ql, qr, n, m;
ll a[MAXN], in[MAXN], val;
ll gcd(ll a, ll b)
{
return b == 0 ? a : gcd(b, a % b);
}
void up(int k)
{
que[k].sum = que[k << 1].sum + que[k << 1 | 1].sum;
que[k].maxn = max(que[k << 1].maxn, que[k << 1 | 1].maxn);
que[k].minn = min(que[k << 1].minn, que[k << 1 | 1].minn);
que[k].gcds = gcd(que[k << 1].gcds, que[k << 1 | 1].gcds);
}
void build(int left = 1, int right = n, int k = 1)
{
que[k].l = left;
que[k].r = right;
if (left == right)
{
que[k].sum = a[left];
que[k].maxn = a[left];
que[k].minn = a[left];
que[k].gcds = a[left];
return;
}
imid;
build(lson);
build(rson);
up(k);
}
void update(int left = 1, int right = n, int k = 1)
{
if (qr < left || right < ql)
return;
if (ql == left && right == qr)
{
que[k].sum += val;
que[k].maxn += val;
que[k].minn += val;
que[k].gcds = que[k].sum;
return;
}
imid;
update(lson);
update(rson);
up(k);
}
ll querysum(int left = 1, int right = n, int k = 1)
{
if (qr < left || right < ql)
return 0;
if (ql <= left && right <= qr)
return que[k].sum;
imid;
return querysum(lson) + querysum(rson);
}
ll querymax(int left = 1, int right = n, int k = 1)
{
if (qr < left || right < ql)
return -1000000000000000000;
if (ql <= left && right <= qr)
return que[k].maxn;
imid;
return max(querymax(lson), querymax(rson));
}
ll querymin(int left = 1, int right = n, int k = 1)
{
if (qr < left || right < ql)
return 1000000000000000000;
if (ql <= left && right <= qr)
return que[k].minn;
imid;
return min(querymin(lson), querymin(rson));
}
ll querygcd(int left = 1, int right = n, int k = 1)
{
if (qr < left || right < ql)
return 0;
if (ql <= left && right <= qr)
return que[k].gcds;
imid;
return gcd(querygcd(lson), querygcd(rson));
}
int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
{
scanf("%d", &in[i]);
a[i] = in[i] - in[i - 1];
}
build();
int q, w, op;
while (m--)
{
scanf("%d%d%d", &op, &q, &w);
if (op == 1)
{
scanf("%lld", &val);
ql = q;
qr = q;
update();
ql = w + 1;
qr = w + 1;
val = -val;
update();
}
else if (op == 2)
{
ql = q + 1;
qr = w;
ll ans = max(0LL, max(querymax(), -querymin()));
printf("%lld\n", ans);
}
else
{
ql = 1;
qr = q;
ll res1 = querysum();
ql = q + 1;
qr = w;
ll res2 = querygcd();
printf("%lld\n", abs(gcd(res1, res2)));
}
}
}