传送门
线段树辣鸡题。
题意简述:给出一个序列,支持修改其中一个数,以及在允许自行修改某个数的情况下询问区间
[
l
,
r
]
[l,r]
[l,r]的
g
c
d
gcd
gcd是否可能等于一个给定的数。
看完题就感觉是道线段树。
修改操作不谈了。
查询给人的第一感觉有点新奇。
但仔细分析就是
s
b
sb
sb操作了。
我们维护一个全局变量
c
n
t
cnt
cnt来记录为了达到要求已经修改了几个数,如果
c
n
t
>
1
cnt>1
cnt>1剪枝就行了。
代码:
#include<bits/stdc++.h>
#define ri register int
#define lc (p<<1)
#define rc (p<<1|1)
#define mid (T[p].l+T[p].r>>1)
using namespace std;
const int N=5e5+5;
inline int read(){
int ans=0;
char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
return ans;
}
int n,a[N],q,cnt;
struct Node{int l,r,g;}T[N<<2];
inline void pushup(int p){T[p].g=__gcd(T[lc].g,T[rc].g);}
inline void build(int p,int l,int r){
T[p].l=l,T[p].r=r;
if(l==r){T[p].g=a[l];return;}
build(lc,l,mid),build(rc,mid+1,r),pushup(p);
}
inline void update(int p,int k,int v){
if(T[p].l==T[p].r){T[p].g=v;return;}
if(k<=mid)update(lc,k,v);
else update(rc,k,v);
pushup(p);
}
inline void query(int p,int ql,int qr,int v){
if(cnt>=2)return;
if(ql<=T[p].l&&T[p].r<=qr){
if(T[p].g%v==0)return;
if(T[p].l==T[p].r){++cnt;return;}
if(T[lc].g%v&&T[rc].g%v){cnt+=2;return;}
T[lc].g%v?query(lc,ql,qr,v):query(rc,ql,qr,v);
return;
}
if(qr<=mid)return query(lc,ql,qr,v);
if(ql>mid)return query(rc,ql,qr,v);
query(lc,ql,mid,v),query(rc,mid+1,qr,v);
}
int main(){
n=read();
for(ri i=1;i<=n;++i)a[i]=read();
build(1,1,n);
for(ri tt=read(),l,r,x,op;tt;--tt){
op=read();
if(op==1)l=read(),r=read(),x=read(),cnt=0,query(1,l,r,x),puts(cnt<2?"YES":"NO");
else l=read(),x=read(),update(1,l,x);
}
return 0;
}