分析:
没想到这道题还能二分查找...
这题主席树的话,裸的很显然...我们将每一个数分解质因数,之后建一个可持久化权值线段树维护[L,R]区间内的每一种质因子的个数,分解质因数的话,可以选择用线筛,总体时间复杂度为O(qlognlogn+nlogn+n);之后的常数巨大,比根号跑的还慢...当然,主席树可以只维护质数,这样能减少一个log,快上不少。
附上代码:
#include <cstdio> #include <algorithm> #include <cmath> #include <cstring> #include <cstdlib> #include <queue> #include <iostream> using namespace std; #define N 100005 #define maxn 100000 #define lson l,m,tr[rt].ls #define rson m+1,r,tr[rt].rs #define clear(rt) tr[rt].ls=tr[rt].rs=tr[rt].siz=0 struct node { int ls,rs,siz; }tr[N*200]; inline char nc() { static char buf[100000],*p1,*p2; return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; } inline int rd() { int x=0;char s=nc(); while(s<'0'||s>'9') s=nc(); while(s>='0'&&s<='9') x=(x<<3)+(x<<1)+s-'0',s=nc(); return x; } int rot[N],pri[N],vis[N],p[N],n,Q,a[N],cnt; void init() { int num=0; for(int i=2;i<N;i++) { if(!vis[i]) { pri[++num]=i; p[i]=i; } for(int j=1;j<=num&&i*pri[j]<N;j++) { vis[i*pri[j]]=1;p[i*pri[j]]=pri[j]; if(i%pri[j]==0)break; } } } void insert(int x,int v,int c,int l,int r,int &rt) { rt=++cnt,clear(cnt); if(l==r){tr[rt].siz=tr[x].siz+c;return ;} int m=(l+r)>>1; if(m>=v)tr[rt].rs=tr[x].rs,insert(tr[x].ls,v,c,lson); else tr[rt].ls=tr[x].ls,insert(tr[x].rs,v,c,rson); tr[rt].siz=tr[tr[rt].ls].siz+tr[tr[rt].rs].siz; } int query(int x,int v,int l,int r,int rt) { //if(l==r)printf("%d %d %d ",l,r,tr[rt].siz-tr[x].siz); if(l==r)return tr[rt].siz-tr[x].siz; int m=(l+r)>>1; if(m>=v)return query(tr[x].ls,v,lson); return query(tr[x].rs,v,rson); } int main() { int T;T=rd(); init(); while(T--) { rot[0]=cnt=0; n=rd();Q=rd(); for(int i=1;i<=n;i++) { a[i]=rd();rot[i]=rot[i-1]; int t=a[i]; while(t!=1)insert(rot[i],p[t],1,1,maxn,rot[i]),t=t/p[t]; } while(Q--) { int x,y,z; x=rd();y=rd();z=rd(); int t=z,u=0; while(t!=1) { //printf("%d ",p[t]); if(query(rot[x-1],p[t],1,maxn,rot[y])) { insert(rot[y],p[t],-1,1,maxn,rot[y]); }else { u=1; puts("No"); break; } t=t/p[t]; } while(z!=t) { insert(rot[y],p[z],1,1,maxn,rot[y]); z=z/p[z]; } if(!u)puts("Yes"); } } return 0; }