题目大意:Bash喜欢对数列进行操作。第一种操作是询问l~r区间内的gcd值是否几乎为x,几乎为表示能否至多修改一个数达到。第二种操作是将ai修改为x。总共Q个询问,N个数。
Solution:简单来说,就是对区间gcd值的维护,使用线段树实现。
code:
#include <cstdio> using namespace std; int read() { char c;while(c=getchar(),c<'0'||c>'9'); int x=c-'0';while(c=getchar(),c>='0'&&c<='9')x=x*10+c-'0'; return x; } const int MAXN=5*100000+5; int N,Q,a[MAXN],o,cnt,x,y,c; int seg[MAXN*4]; int gcd(int x,int y){return !y?x:gcd(y,x%y);} void build(int node,int l,int r) { if(l==r)seg[node]=a[l]; else{ int mid=l+r>>1; build(node<<1,l,mid); build(node<<1|1,mid+1,r); seg[node]=gcd(seg[node<<1],seg[node<<1|1]);//更行该节点的值 } return ; }//建树 void change(int node,int l,int r,int dist,int v) { if(l==dist && r==dist){ seg[node]=v; return ; }//到达要修改的节点 int mid=l+r>>1; if(mid>=dist)change(node<<1,l,mid,dist,v); else change(node<<1|1,mid+1,r,dist,v); seg[node]=gcd(seg[node<<1],seg[node<<1|1]);//更新 return ; } void get(int l,int r,int ql,int qr,int node,int v) { if(cnt>1)return ;//优化 if(l==r){//此处之所以可以这样,因为我们在搜到这个点之前保证了这个点的seg值%v不为0 cnt++; return ; } int mid=l+r>>1; if(mid>=ql&&seg[node<<1]%v/*此处为上面做法的原因*/) get(l,mid,ql,qr,node<<1,v); if(mid<qr &&seg[node<<1|1]%v)get(mid+1,r,ql,qr,node<<1|1,v); return ; } void find(int x,int y,int c) { cnt=0;get(1,N,x,y,1,c); if(cnt<=1)puts("YES"); else puts("NO"); return ; } int main() { N=read(); register int i,j; for(i=1;i<=N;i++)a[i]=read(); build(1,1,N); Q=read(); while(Q--){ o=read(); if(o==1){x=read(),y=read(),c=read(),find(x,y,c);} else {x=read(),y=read(),change(1,1,N,x,y);} } return 0; }