题意:
操作 1 l 到 r 的区间加上x
操作2 l到 r 相邻两个差值的绝对值最大 l==r输出0
操作3 l 到 r 的gcd
难点就是是gcd 要想求区间能修改的gcd 你必须要知道一些知识
gcd(a,b)=gcd(a,b-a). gcd(a,b,c)=gcd(a,b-a,c-a) 以此类推
然后只要线段树 维护 相邻两个的差值就可以了 当遇到 操作1
时 由于一个区间的加上相同的数 只有 第一个 和最后一个值改变了因此只有单点修改第一个 与最后一个就行了 即 第一个加上x 最后一个的下一个减去x
代码
#include
using namespace std;
const int N=1e5+7;
int n,Q,p[N],h[N];
int add[N];
int gcd(int a,int b){return b?gcd(b,a%b):a;}
struct node{
int v,g,maxn;
}tree[4*N];
#define lson 2*node
#define rson 2*node+1
#define m (l+r)/2
void build(int l,int r,int node){
if(l==r){
tree[node].v=p[l];
tree[node].g=h[l];
tree[node].maxn=h[l];
return;
}
build(l,m,lson);
build(m+1,r,rson);
tree[node].g=gcd(tree[lson].g,tree[rson].g);
tree[node].maxn=max(abs(tree[lson].maxn),abs(tree[rson].maxn));
}
void push_down(int node){
if(add[node]){
tree[lson].v+=add[node];
tree[rson].v+=add[node];
add[lson]+=add[node];
add[rson]+=add[node];
add[node]=0;
}
}
void update(int v,int ql,int qr,int l,int r,int node){
if(ql<=l&&qr>=r){
tree[node].v+=v;
add[node]+=v;
return;
}
push_down(node);
if(ql<=m)update(v,ql,qr,l,m,lson);
if(qr>m)update(v,ql,qr,m+1,r,rson);
}
void upgcd(int v,int pos,int l,int r,int node){
if(l==r){
tree[node].g+=v;
tree[node].maxn+=v;
return;
}
if(pos<=m)upgcd(v,pos,l,m,lson);
else upgcd(v,pos,m+1,r,rson);
tree[node].g=gcd(tree[lson].g,tree[rson].g);
tree[node].maxn=max(abs(tree[lson].maxn),abs(tree[rson].maxn));
}
int query(int ql,int qr,int l,int r,int node){
if(ql<=l&&qr>=r) return tree[node].g;
int ans=0;
if(ql<=m)ans=gcd(ans,query(ql,qr,l,m,lson));
if(qr>m)ans=gcd(ans,query(ql,qr,m+1,r,rson));
return ans;
}
int querymax(int ql,int qr,int l,int r,int node){
if(ql>qr)return 0;
if(ql<=l&&qr>=r){
return abs(tree[node].maxn);
}
int ans=0;
if(ql<=m)ans=max(ans,querymax(ql,qr,l,m,lson));
if(qr>m)ans=max(ans,querymax(ql,qr,m+1,r,rson));
return ans;
}
int queryvalue(int pos,int l,int r,int node){
if(l==r)return tree[node].v;
push_down(node);
if(pos<=m)return queryvalue(pos,l,m,lson);
return queryvalue(pos,m+1,r,rson);
}
int main(){
scanf("%d%d",&n,&Q);
for(int i=1;i<=n;i++){
scanf("%d",&p[i]);
h[i]=p[i]-p[i-1];
}
build(1,n,1);
int q,l,r,x;
while(Q--){
scanf("%d%d%d",&q,&l,&r);
if(q==1){
scanf("%d",&x);
update(x,l,r,1,n,1);
upgcd(x,l,1,n,1);
if(r+1<=n)upgcd(-x,r+1,1,n,1);
}else if(q==2){
printf("%d\n",querymax(l+1,r,1,n,1));
}else if(q==3){
if(l==r)printf("%d\n",queryvalue(l,1,n,1));
else{
int ans=queryvalue(l,1,n,1);
ans=gcd(ans,query(l+1,r,1,n,1));
printf("%d\n",abs(ans));
}
}
}
}