有点考验思维
首 先 区 间 查 询 , 单 点 修 改 , 想 到 线 段 树 可 以 维 护 区 间 g c d 首先区间查询,单点修改,想到线段树可以维护区间gcd 首先区间查询,单点修改,想到线段树可以维护区间gcd
主 要 是 查 询 区 间 g c d 是 否 是 x 怎 么 办 。 主要是查询区间gcd是否是x怎么办。 主要是查询区间gcd是否是x怎么办。
我 们 只 能 查 询 区 间 的 g c d , 但 是 这 里 可 以 修 改 1 个 数 我们只能查询区间的gcd,但是这里可以修改1个数 我们只能查询区间的gcd,但是这里可以修改1个数
若 区 间 g c d 是 x 的 倍 数 , 就 别 去 管 了 \color{Red}若区间gcd是x的倍数,就别去管了 若区间gcd是x的倍数,就别去管了
不 用 管 是 否 是 几 倍 , 是 几 倍 都 可 以 改 变 一 个 变 成 x 使 得 g c d = x 不用管是否是几倍,是几倍都可以改变一个变成x使得gcd=x 不用管是否是几倍,是几倍都可以改变一个变成x使得gcd=x
若 区 间 g c d 不 是 x 的 倍 数 , 一 直 向 下 查 询 直 到 叶 子 节 点 \color{Red}若区间gcd不是x的倍数,一直向下查询直到叶子节点 若区间gcd不是x的倍数,一直向下查询直到叶子节点
那 么 这 个 叶 子 节 点 肯 定 要 修 改 , 我 们 把 它 修 改 为 x 那么这个叶子节点肯定要修改,我们把它修改为x 那么这个叶子节点肯定要修改,我们把它修改为x
修 改 成 x 的 好 处 是 , 就 算 其 他 区 间 g c d 是 x 的 倍 数 , 最 后 g c d 也 会 变 成 x 修改成x的好处是,就算其他区间gcd是x的倍数,最后gcd也会变成x 修改成x的好处是,就算其他区间gcd是x的倍数,最后gcd也会变成x
所以问题转化为查询区间有几个数不是x的倍数
若 都 是 x 的 倍 数 , 显 然 改 变 一 个 数 为 x 就 可 以 满 足 条 件 若都是x的倍数,显然改变一个数为x就可以满足条件 若都是x的倍数,显然改变一个数为x就可以满足条件
若 只 有 一 个 数 不 是 x 的 倍 数 , 显 然 改 变 这 个 数 为 x 可 以 满 足 条 件 若只有一个数不是x的倍数,显然改变这个数为x可以满足条件 若只有一个数不是x的倍数,显然改变这个数为x可以满足条件
否 则 , 必 定 不 满 足 否则,必定不满足 否则,必定不满足
#include <bits/stdc++.h>
using namespace std;
#define lson p<<1,l,mid
#define int long long
#define rson p<<1|1,mid+1,r
const int maxn=2e6+10;
int n,val[maxn],cnt,q;
int gcd(int a,int b){
return b==0?a:gcd(b,a%b);
}
struct xian{
int l,r,v;
}a[maxn];
void push_up(int p){
a[p].v=gcd( a[p<<1].v,a[p<<1|1].v );
}
void build(int p,int l,int r)
{
a[p] = (xian){l,r,0};
if( l==r )
{
a[p].v=val[l];
return;
}
int mid=l+r>>1;
build(lson); build(rson);
push_up(p);
}
void change(int p,int l,int r,int k)
{
if( a[p].l>=l&&a[p].r<=r )
{
a[p].v=k;
return;
}
int mid=a[p].l+a[p].r>>1;
if( mid>=l ) change(p<<1,l,r,k);
if( mid<r ) change(p<<1|1,l,r,k);
push_up(p);
}
void ask(int p,int l,int r,int x)//查询区间l,r
{
if( cnt>1 ) return;
if( a[p].v%x==0 ) return;
if( a[p].l==a[p].r )//叶子节点不包含x因子
{
cnt++;
return;
}
int mid=a[p].l+a[p].r>>1;
if( mid>=l ) ask(p<<1,l,r,x);
if( mid<r ) ask(p<<1|1,l,r,x);
}
signed main()
{
scanf("%lld",&n);
for(int i=1;i<=n;i++) scanf("%lld",&val[i]);
build(1,1,n);
scanf("%lld",&q);
while( q-- )
{
int ok,l,r,x;
scanf("%d",&ok);
if( ok==1 )
{
scanf("%lld%lld%lld",&l,&r,&x);
cnt=0;
ask(1,l,r,x);
if( cnt<=1 ) puts("YES");
else puts("NO");
}
else
{
scanf("%lld%lld",&l,&x);
change(1,l,l,x);
}
}
}