小阳的贝壳
题目大意:
给你一个长度为n的数组,有初值,三种操作;
- 给区间[l,r]所有数加上x;
- 询问区间[l,r]相邻的元素差值最大值(取绝对值);
- 询问区间[l,r]所有数的最大公约数;
最难的就是第三问了,运用到了gcd的一些原理,如果不是很懂得话想不到;
gcd(a,b,c)=gcd(a,b-a,c-b)=gcd(a,gcd(b-a,c-b));
依此类推,不就是维护一个差分数组,如果求[l,r]的最大公约数,不就是求
gcd(a[l],gcd(b[l+1]…b[r]));(a[]代表原数组,b[]代表差分数组)
代码:
#include<bits/stdc++.h>
#define LL long long
#define pa pair<int,int>
#define ls k<<1
#define rs k<<1|1
#define inf 0x3f3f3f3f
using namespace std;
const int N=100100;
const int M=2000000;
const LL mod=1e9+7;
int n,m,a[N];
struct Node{
int l,r,sum,mx,mg;
}tr[N*4];
void pp(int k){
tr[k].mx=max(tr[ls].mx,tr[rs].mx);
tr[k].mg=__gcd(tr[ls].mg,tr[rs].mg);
tr[k].sum=tr[ls].sum+tr[rs].sum;
}
void build(int l,int r,int k){
tr[k].l=l,tr[k].r=r;
if(l==r){
tr[k].mx=tr[k].mg=abs(a[l]);
tr[k].sum=a[l];
return;
}
int d=(l+r)>>1;
build(l,d,ls);build(d+1,r,rs);
pp(k);
}
void update(int pos,int w,int k){
if(tr[k].l==tr[k].r){
a[tr[k].l]+=w;
tr[k].sum=a[tr[k].l];
tr[k].mx=tr[k].mg=abs(a[tr[k].l]);
return;
}
int d=(tr[k].l+tr[k].r)>>1;
if(pos<=d) update(pos,w,ls);
else update(pos,w,rs);
pp(k);
}
int query_max(int l,int r,int k){
if(l>r) return 0;
if(tr[k].l>=l&&tr[k].r<=r) return tr[k].mx;
int mx=0;
int d=(tr[k].l+tr[k].r)>>1;
if(l<=d) mx=max(query_max(l,r,ls),mx);
if(r>d) mx=max(query_max(l,r,rs),mx);
return mx;
}
int query_sum(int l,int r,int k){
if(tr[k].l>=l&&tr[k].r<=r) return tr[k].sum;
int sum=0;
int d=(tr[k].l+tr[k].r)>>1;
if(l<=d) sum+=query_sum(l,r,ls);
if(r>d) sum+=query_sum(l,r,rs);
return sum;
}
int query_gcd(int l,int r,int k){
if(tr[k].l>=l&&tr[k].r<=r) return tr[k].mg;
int mg=0;
int d=(tr[k].l+tr[k].r)>>1;
if(l<=d) mg=__gcd(mg,query_gcd(l,r,ls));
if(r>d) mg=__gcd(mg,query_gcd(l,r,rs));
return mg;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=n;i>=1;i--) a[i]-=a[i-1];//差分数组
build(1,n,1);
for(int i=1;i<=m;i++){
int opt;scanf("%d",&opt);
if(opt==1){
int l,r,x;scanf("%d%d%d",&l,&r,&x);
update(l,x,1);//单点更新
if(r<n) update(r+1,-x,1);//单点更新
}
else if(opt==2){
int l,r;scanf("%d%d",&l,&r);
printf("%d\n",query_max(l+1,r,1));
}
else{
int l,r;scanf("%d%d",&l,&r);
printf("%d\n",__gcd(query_sum(1,l,1),query_gcd(l+1,r,1)));
}
}
return 0;
}