把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; }