题目传送
很明显的线段树,不过需要判断一下gcd
#include <iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<climits>
#include<vector>
#include<queue>
#include<string>
#include <cmath>
#include<set>
#define mod 999997
#define lson l, mid, root << 1
#define rson mid + 1, r, root << 1 | 1
#define father l , r , root
#define lowbit(x) ( x & ( - x ) )
using namespace std;
typedef long long ll;
const int maxn = 5e5+5;
const int inf = 0x3f3f3f3f;
int num[maxn];
int Gcd[maxn<<2];
int lazy[maxn<<2];
int gcd(int a,int b){
return b==0?a:gcd(b,a%b);
}
void push_up(int root){
Gcd[root]=gcd(Gcd[root<<1],Gcd[root<<1|1]);//向上更新
}
void push_down(int root){//向下更新
if(lazy[root]==0) return ;
Gcd[root<<1]=lazy[root];
Gcd[root<<1|1]=lazy[root];
lazy[root<<1]=lazy[root];
lazy[root<<1|1]=lazy[root];
lazy[root]=0;//取消标记
}
void build_tree(int l,int r,int root){
lazy[root]=0;//初始化
if(l==r){
Gcd[root]=num[l];
return ;
}
int mid=(l+r)>>1;
build_tree(lson);
build_tree(rson);
push_up(root);
}
void change(int L,int R,int val,int l,int r ,int root){
if(L<=l&&R>=r){
Gcd[root]=val;
lazy[root]=val;
return ;
}
push_down(root);//向下更新
int mid=(l+r)>>1;
if(mid>=L)change(L,R,val,lson);
if(mid<R)change(L,R,val,rson);
push_up(root);//回溯时向上更新
}
int query(int L,int R,int l,int r ,int root){
if(L<=l&&R>=r){
return Gcd[root];
}
push_down(root);
int ans1,ans2;
int mid=(l+r)>>1;
if(mid>=R){//全在左区间
return query(L,R,lson);
}else if(mid<L){//全在右区间
return query(L,R,rson);
}else{//左右区间存在
ans1=query(L,R,lson);
ans2=query(L,R,rson);
return gcd(ans1,ans2);
}
}
int main( ){
int t;
scanf("%d",&t);
while(t--){
int n,q;
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)scanf("%d",&num[i]);
build_tree(1,n,1);
while(q--){
int flag,l,r,x;
scanf("%d",&flag);
if(flag==1){
scanf("%d%d%d",&l,&r,&x);
change(l,r,x,1,n,1);
}else{
scanf("%d%d",&l,&r);
printf("%d\n",query(l,r,1,n,1));
}
}
}
return 0;
}