914D Bash and a Tough Math Puzzle
分析
用线段树维护区间gcd,每次查询找到第一个不是x倍数的点,如果这之后还有gcd不能被x整除的区间则这个区间不合法
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
int d[2000100],cnt,a[500100];
inline int gcd(int x,int y){return y==0?x:gcd(y,x%y);}
inline void build(int le,int ri,int wh){
if(le==ri){
d[wh]=a[le];
return;
}
int mid=(le+ri)>>1;
build(le,mid,wh<<1);
build(mid+1,ri,wh<<1|1);
d[wh]=gcd(d[wh<<1],d[wh<<1|1]);
return;
}
inline void update(int le,int ri,int wh,int pl,int k){
if(le==ri){
d[wh]=k;
return;
}
int mid=(le+ri)>>1;
if(mid>=pl)update(le,mid,wh<<1,pl,k);
else update(mid+1,ri,wh<<1|1,pl,k);
d[wh]=gcd(d[wh<<1],d[wh<<1|1]);
return;
}
inline void q(int le,int ri,int wh,int x,int y,int k){
if(le>=x&&ri<=y){
if(d[wh]%k==0)return;
if(cnt>=1){
cnt++;
return;
}
}
if(le==ri){
cnt++;
return;
}
int mid=(le+ri)>>1;
if(mid>=x)q(le,mid,wh<<1,x,y,k);
if(mid<y)q(mid+1,ri,wh<<1|1,x,y,k);
return;
}
int main(){
int n,m,i,j,k,x,y,z;
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%d\n",&a[i]);
build(1,n,1);
scanf("%d",&m);
for(i=1;i<=m;i++){
scanf("%d",&k);
if(k==1){
scanf("%d%d%d",&x,&y,&z);
cnt=0;
q(1,n,1,x,y,z);
if(cnt>1)puts("NO");
else puts("YES");
}else {
scanf("%d%d",&x,&y);
update(1,n,1,x,y);
}
}
return 0;
}