分析
用线段树维护区间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; }
原文地址:https://www.cnblogs.com/yzxverygood/p/9749344.html
时间: 2024-10-11 18:19:04