题意:q次询问,每次两个操作,1.问你区间【l,r】内修改一个数字后,区间的gcd是否是X,2.单点修改区间【l,r】的值
题解:线段树处理区间的gcd
- 如果给定的区间【l,r】 在左子树,就在左子树找
- 否则在右子树找
- 在否则需要拆区间,这时再来个查询,查询拆区间后的左右子树的gcd是否能整除X,因为区间gcd一定是最小的内个数
- 如果拆区间后的左右子树一边能整除则继续往下搜
- 如果拆区间后的左右子树两边都能整除,那就可以返回了,此时修改后gcd一定能是X;
- 如果拆区间后的左右子树两边都不能整除,那也可以返回了,只是此时修改后gcd一定不是X;
- 由于查询套查询所以是loglog级别,也可以接受,但可以是一个log的,通过拆要查的区间就好了。
-
int lgcd=find_gcd(l,mid,L,mid,p<<1); int rgcd=find_gcd(mid+1,r,mid+1,R,p<<1|1);
#include <bits/stdc++.h> #define ll long long using namespace std; const int maxn = 1e6 + 5; const int INF = 0x3f3f3f3f; const ll MOD = 1e9 + 7; int gg[maxn*4]; int a[maxn]; void build(int l,int r,int p){ if(l==r) { gg[p]=a[l]; return ; } int mid=(l+r)/2; build(l,mid,p<<1); build(mid+1,r,p<<1|1); gg[p]=__gcd(gg[p<<1],gg[p<<1|1]); } void update(int l,int r,int p,int pos,int v){ if(l==r) { gg[p]=v; return ; } int mid=(l+r)/2; if(pos<=mid) update(l,mid,p<<1,pos,v); else update(mid+1,r,p<<1|1,pos,v); gg[p]=__gcd(gg[p<<1],gg[p<<1|1]); } int find_gcd(int l,int r,int L,int R,int p){ if(L<=l&&r<=R){ return gg[p]; } int mid=(l+r)/2; int res=0; if(L<=mid) res=__gcd(res,find_gcd(l,mid,L,R,p<<1)); if(R>mid) res=__gcd(res,find_gcd(mid+1,r,L,R,p<<1|1)); return res; } int query(int l,int r,int L,int R,int p,int x){ if(l==r) return 1; int mid=(l+r)/2; int res=0; if(R<=mid) res=query(l,mid,L,R,p<<1,x);//直接进左树找gcd else if(L>mid) res=query(mid+1,r,L,R,p<<1|1,x);//右树找gcd else{//得拆区间 int lgcd=find_gcd(l,mid,L,mid,p<<1); int rgcd=find_gcd(mid+1,r,mid+1,R,p<<1|1); if(lgcd%x!=0&&rgcd%x!=0) return 0;//如果拆完的两边都%==0,则一定改变一个数可以使最大公约数变为x (lgcd/rgcd 都取决与他区间里最小的数) if(!(lgcd%x)&&!(rgcd%x)) return 1;//负责 直接不可能 if(lgcd%x==0&&rgcd%x!=0) res=query(mid+1,r,L,R,p<<1|1,x);//如果一边区间满足继续搜 if(lgcd%x!=0&&rgcd%x==0) res=query(l,mid,L,R,p<<1,x); } return res; } int main(){ std::ios::sync_with_stdio(false); int n; cin>>n; for(int i=1;i<=n;i++) cin>>a[i]; int q; cin>>q; build(1,n,1); while(q--){ int k; cin>>k; if(k==1){ int l,r,x; cin>>l>>r>>x; int flag=query(1,n,l,r,1,x); if(flag) cout<<"YES"<<endl; else cout<<"NO"<<endl; }else{ int i,y; cin>>i>>y; update(1,n,1,i,y); } } return 0; }