用莫队求出每个询问区间对应的bitset(表示每个权值是否出现过),对于加减可以用bitset移位后取and判断,对于乘法可以直接枚举约数
#include<bits/stdc++.h> int _(){ int x=0,c=getchar(); while(c<48)c=getchar(); while(c>47)x=x*10+c-48,c=getchar(); return x; } const int N=100007,M=100100/32; typedef unsigned int bits[M]; int n,m,B; int t[N],a[N],id[N]; bool as[N]; bits b1,b2; void rev(bits a,int x){a[x>>5]^=1<<(x&31);} bool chk(bits A,bits B,int x){ int a=x>>5,b=x&31; if(b){ int c=32-b; for(int i=a;i<M-1;++i)if((A[i]>>b|A[i+1]<<c)&B[i-a])return 1; }else{ for(int i=a;i<M;++i)if(A[i]&B[i-a])return 1; } return 0; } struct Q{ int o,l,r,x,id; void work(){ if(o==1){ as[id]=chk(b1,b1,x); }else if(o==2){ as[id]=chk(b2,b1,100000-x); }else{ for(int i=1;i*i<=x;++i)if(x%i==0&&t[i]&&t[x/i]){ as[id]=1; return; } } } }qs[N]; bool operator<(Q a,Q b){ if(id[a.l]!=id[b.l])return id[a.l]<id[b.l]; if(a.r!=b.r)return (a.r<b.r)!=(id[a.l]&1); return a.id<b.id; } void ins(int x){ if(!t[x]++)rev(b1,x),rev(b2,100000-x); } void del(int x){ if(!--t[x])rev(b1,x),rev(b2,100000-x); } int main(){ n=_();m=_(); B=n/sqrt(m+1); for(int i=1;i<=n;++i)a[i]=_(),id[i]=(i-1)/B; for(int i=0;i<m;++i){ qs[i].o=_(); qs[i].l=_(); qs[i].r=_(); qs[i].x=_(); qs[i].id=i; } std::sort(qs,qs+m); int L=1,R=0; for(int i=0;i<m;++i){ int l=qs[i].l,r=qs[i].r; while(L>l)ins(a[--L]); while(R<r)ins(a[++R]); while(L<l)del(a[L++]); while(R>r)del(a[R--]); qs[i].work(); } for(int i=0;i<n;++i)puts(as[i]?"yuno":"yumi"); return 0; }