區間加一個數以及求區間GCDc++
由性質gcd(a,b)=gcd(a,b-a)可得區間gcd可變爲: gcd( a[l], a[l+1], a[l+2],..., a[r] ) = gcd( a[l], a[l+1] - a[l] , a[l+2] - a[l+1] ,..., a[r] - a[r-1] )。數組
先把數組變爲差分數組,因此區間加的時候能夠知道除了第一個數之外其餘數都不變(-v又+v)。ssh
因此區間加變爲在區間最左端單點加,在區間最右端+1單點減便可。ide
#include <bits/stdc++.h> #define pb push_back #define mp make_pair #define fi first #define se second #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define up rt,rt<<1,rt<<1|1 #define mem(x) memset(x,0,sizeof(x)) #define mem1(x) memset(x,-1,sizeof(x)) //#define LMissher using namespace std; typedef long long ll; typedef double db; const int M = 1e5+7; const double pi = acos(-1); const int inf = 2147483647; const int mod = 1e9+7; int n,sum[M<<2],g[M<<2],a[M],q,pos; void pushup(int rt,int l,int r){ sum[rt]=sum[l]+sum[r]; g[rt]=__gcd(g[l],g[r]); } void build(int l,int r,int rt){ if(l==r){ sum[rt]=g[rt]=a[l]-(l==1?0:a[l-1]);//差分 return ; } int mid=(l+r)>>1; build(lson); build(rson); pushup(up); } void update(int l,int r,int rt,int v){ if(l==r){ sum[rt]+=v; g[rt]+=v; return ; } int mid=(l+r)>>1; if(pos<=mid) update(lson,v); else update(rson,v); pushup(up); } int query(int L,int R,int l,int r,int rt,int op){ if(L<=l&&r<=R){ if(op==1) return sum[rt]; else return g[rt]; } int mid=(l+r)>>1,ans=0; if(L<=mid){ if(op==1) ans+=query(L,R,lson,op); else ans=__gcd(ans,query(L,R,lson,op)); } if(R>mid){ if(op==1) ans+=query(L,R,rson,op); else ans=__gcd(ans,query(L,R,rson,op)); } return ans; } int main(){ #ifdef LMissher freopen("1.in","r",stdin); freopen("1.out","w",stdout); #endif scanf("%d%d",&n,&q); for(int i=1;i<=n;i++) scanf("%d",&a[i]); build(1,n,1); int op; while(q--){ int l,r,v; scanf("%d",&op); scanf("%d%d",&l,&r); if(l>r) swap(l,r); if(op==1){ printf("%d\n",abs(__gcd(query(1,l,1,n,1,1),query(l+1,r,1,n,1,2)))); } else{ scanf("%d",&v); pos=l; update(1,n,1,v); if(r+1<=n){ pos=r+1; update(1,n,1,-v); } } } return 0; }