The meaning of problems
Given a sequence of two operations, one is seeking gcd interval period, the other is to add a value interval period. (See it is as to why the interval gcd, that Italy should be in the range inside the bottle shuffling back and forth, and finally you want a bottle of oil to the customer, then according to Theorem Shu Pei what can know )
answer
According to known technique Decreases gcd (x, y) = gcd (x, yx), then readily available for the three numbers gcd (x, y, z) = gcd (x, yx, zy);
Easy to use mathematical induction to prove any integer multiple of the nature of the heap are established
The above formula is not like there is a difference?
Therefore, we can use the difference to modify the interval into two modified single point, when modifying only know a [l] and [l + 1, r] can gcd this difference interval.
For differential arrays we can build segment tree maintenance intervals gcd, for the value of a single point of maintenance can be used Fenwick tree.
Note that the query, if l == r gives directly a [l] to a value, or the determination of the segment tree Laid query returns 0, take folk abs
Modifying if r == n r + 1 is not to change the
#include<bits/stdc++.h> using namespace std; const int maxn=100005; int n,m,root,num; int a[maxn],b[maxn]; int ls[maxn<<1],rs[maxn<<1],gcd[maxn<<1]; int cx[maxn]; template<class T>inline void read(T &x){ x=0;char ch=getchar(); while(!isdigit(ch)) ch=getchar(); while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} } int get_gcd(int a,int b){ return !b ? a : get_gcd(b,a%b); } void update(int rt){ gcd[rt]=get_gcd(gcd[ls[rt]],gcd[rs[rt]]); } void build(int &rt,int l,int r){ if(!rt) rt=++num; if(l==r) {gcd[rt]=a[l];return ;} int mid=(l+r)>>1; build(ls[rt],l,mid); build(rs[rt],mid+1,r); update(rt); } void add(int x,int val){for(;x<=n;x+=x&-x) cx[x]+=val;} int sum(int x){ int ret=0; for(;x;x-=x&-x) ret+=cx[x]; return ret; } int query(int rt,int l,int r,int L,int R){ if(L<=l&&r<=R) return gcd[rt]; int mid=(l+r)>>1; if(R<=mid) return query(ls[rt],l,mid,L,R); if(mid<L) return query(rs[rt],mid+1,r,L,R); return get_gcd(query(ls[rt],l,mid,L,R),query(rs[rt],mid+1,r,L,R)); } void modify(int rt,int l,int r,int pos,int val){ if(l==r){ gcd[rt]+=val; return ; } int mid=(l+r)>>1; if(pos<=mid) modify(ls[rt],l,mid,pos,val); else modify(rs[rt],mid+1,r,pos,val); update(rt); } int main(){ read(n);read(m); for(int i=1;i<=n;i++)read(a[i]); for(int i=n;i;i--) a[i]-=a[i-1],add(i,a[i]); build(root,1,n); for(int i=1;i<=m;i++){ int op,l,r; read(op);read(l);read(r); if(l>r) swap(l,r); if(op==1){ if(l==r) printf("%d\n",sum(l)); else printf("%d\n",abs(get_gcd(sum(l),query(root,1,n,l+1,r)))); } else { int v; read(v); add(l,v);add(r+1,-v); modify(root,1,n,l,v); if(r<n) modify(root,1,n,r+1,-v); } } }