把gcd转化成差值...然后建立两颗线段树....
#include <iostream>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <climits>
#include <cstdlib>
#include <cmath>
#include <time.h>
using namespace std;
typedef long long LL;
#define lson o << 1, L, mid
#define rson o << 1 | 1, mid+1, R
#define ls o << 1
#define rs o << 1 | 1
const LL INF = 1e18;
const int maxn = 100005;
LL g[maxn << 2];
LL val[maxn << 2];
LL lazy[maxn << 2];
LL add[maxn << 2];
LL a[maxn];
LL b[maxn];
int n, m;
void pushup(int o)
{
g[o] = __gcd(g[ls], g[rs]);
}
void pushdown(int o)
{
if(lazy[o]) {
lazy[ls] ^= lazy[o];
lazy[rs] ^= lazy[o];
add[ls] = -add[ls];
add[rs] = -add[rs];
val[ls] = -val[ls];
val[rs] = -val[rs];
lazy[o] = 0;
}
if(add[o]) {
add[ls] += add[o];
add[rs] += add[o];
val[ls] += add[o];
val[rs] += add[o];
add[o] = 0;
}
}
void build(int o, int L, int R)
{
if(L == R) {
g[o] = b[L];
return;
}
int mid = (L + R) >> 1;
build(lson);
build(rson);
pushup(o);
}
void build2(int o, int L, int R)
{
lazy[o] = add[o] = 0;
if(L == R) {
val[o] = a[L];
return;
}
int mid = (L + R) >> 1;
build2(lson);
build2(rson);
}
void update1(int o, int L, int R, int ql, int qr, LL v)
{
if(ql <= L && qr >= R) {
val[o] = -val[o];
add[o] = -add[o];
val[o] += v;
add[o] += v;
lazy[o] ^= 1;
return;
}
pushdown(o);
int mid = (L + R) >> 1;
if(ql <= mid) update1(lson, ql, qr, v);
if(qr > mid) update1(rson, ql, qr, v);
}
void update2(int o, int L, int R, int q, LL v)
{
if(L == R) {
g[o] = v;
return;
}
int mid = (L + R) >> 1;
if(q <= mid) update2(lson, q, v);
else update2(rson, q, v);
pushup(o);
}
LL query1(int o, int L, int R, int q)
{
if(L == R) return val[o];
pushdown(o);
int mid = (L + R) >> 1;
if(q <= mid) return query1(lson, q);
else return query1(rson, q);
}
LL query2(int o, int L, int R, int ql, int qr)
{
if(ql <= L && qr >= R) return g[o];
int mid = (L + R) >> 1;
LL ans = 0;
if(ql <= mid) ans = __gcd(ans, query2(lson, ql, qr));
if(qr > mid) ans = __gcd(ans, query2(rson, ql, qr));
return ans;
}
void work()
{
for(int i = 1; i <= n; i++) scanf("%lld", &a[i]);
b[1] = a[1];
for(int i = 2; i <= n; i++) b[i] = a[i] - a[i-1];
build(1, 1, n);
build2(1, 1, n);
while(m--) {
int ql, qr, op;
LL v;
scanf("%d", &op);
scanf("%d%d", &ql, &qr);
if(op == 1) {
scanf("%lld", &v);
update1(1, 1, n, ql, qr, v);
if(ql == 1) {
LL t = query1(1, 1, n, ql);
update2(1, 1, n, ql, t);
}
else {
LL t1 = query1(1, 1, n, ql-1);
LL t2 = query1(1, 1, n, ql);
update2(1, 1, n, ql, t2 - t1);
}
if(qr < n) {
LL t1 = query1(1, 1, n, qr);
LL t2 = query1(1, 1, n, qr + 1);
update2(1, 1, n, qr + 1, t2 - t1);
}
}
else {
LL ans = query1(1, 1, n, ql);
ql++;
if(ql <= qr) {
LL t = query2(1, 1, n, ql, qr);
if(t < 0) t = (t % ans + ans) % ans;
ans = __gcd(ans, t);
}
printf("%lld\n", ans);
}
}
}
int main()
{
//freopen("data", "r", stdin);
while(scanf("%d%d", &n, &m) != EOF) {
work();
}
return 0;
}