对原序列进行差分,得到新的序列。
维护这个序列的最大值,
。
对于区间
求
,只需要求
因为
,更相减损法。
是已经修改之后的值,
code
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int man = 2e5+10;
#define IOS ios::sync_with_stdio(0)
#define endl '\n'
#define ll long long
const ll mod = 1e9+7;
ll a[man],b[man];
ll maxx[man<<2],g[man<<2];
template<typename T>T gcd(T a, T b) {return b==0?a:gcd(b, a%b);}
template<typename T>T exgcd(T a,T b,T &g,T &x,T &y){if(!b){g = a,x = 1,y = 0;}
else {exgcd(b,a%b,g,y,x);y -= x*(a/b);}}
void pushup(int rt){
maxx[rt] = max(abs(maxx[rt<<1]),abs(maxx[rt<<1|1]));
g[rt] = gcd(g[rt<<1],g[rt<<1|1]);
}
void build(int l,int r,int rt){
if(l==r){
g[rt] = b[l];
maxx[rt] = b[l];
return;
}
int m = l + r >> 1;
build(l,m,rt<<1);
build(m+1,r,rt<<1|1);
pushup(rt);
}
void update(int l,int r,int pos,int rt,ll va){
if(l==r){
maxx[rt] += va;
g[rt] = maxx[rt];
return;
}
int m = l +r >>1;
if(pos<=m)update(l,m,pos,rt<<1,va);
else update(m+1,r,pos,rt<<1|1,va);
pushup(rt);
}
ll query_max(int l,int r,int L,int R,int rt){
if(L<=l&&R>=r){
return abs(maxx[rt]);
}
int m = l + r >> 1;
ll ans1 = 0,ans2 = 0;
if(L<=m)ans1 = query_max(l,m,L,R,rt<<1);
if(R>m)ans2 = query_max(m+1,r,L,R,rt<<1|1);
return max(ans1,ans2);
}
ll query_gcd(int l,int r,int L,int R,int rt){
if(L<=l&&R>=r){
return g[rt];
}
int m = l + r >> 1;
ll ans1 = 0,ans2 = 0;
if(L<=m)ans1 = query_gcd(l,m,L,R,rt<<1);
if(R>m)ans2 = query_gcd(m+1,r,L,R,rt<<1|1);
return gcd(ans1,ans2);
}
ll c[man];int n,m;
#define lowbit(x) x&(-x)
void add(int pos,int x){
for(int i = pos;i <= n+5;i +=lowbit(i))c[i] += x;
}
ll query(int pos){
ll ans = 0;
for(int i = pos;i >= 1;i -= lowbit(i)){
ans += c[i];
}
return ans;
}
signed main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
//freopen("out.txt","w",stdout);
#endif
scanf("%d%d",&n,&m);
for(int i = 1;i <= n;++i){
scanf("%lld",a+i);
c[i] = 0;
b[i] = a[i] - a[i-1];
}
build(1,n+5,1);
while(m--){
int op,l,r;
scanf("%d%d%d",&op,&l,&r);
if(1==op){
ll x;scanf("%lld",&x);
add(l,x);add(r+1,-x);
update(1,n+5,l,1,x);
update(1,n+5,r+1,1,-x);
}else if(2==op){
if(l==r)printf("%d\n",0);
else printf("%lld\n",query_max(1,n+5,l+1,r,1));
}else{
ll x = a[l] + query(l);
//cout << "x :" <<x <<endl;
if(l==r)printf("%lld\n",x);
else printf("%lld\n",gcd(x,abs(query_gcd(1,n+5,l+1,r,1))));
}
}
return 0;
}