这题重点不在莫队,在于这个求解方法,挺有意思的
维护一个bitset $stat$表示当前区间的状态,同时反过来(不是通常意义上的反,是从尾到头)维护这个区间的另一状态rsta
对于询问是否有$x$这个差,查询$stat&(stat<<x)$(之中是否有1)
对于询问是否有$x$这个和,查询$stat&(rsta>>(Maxn-x))$(Maxn表示最大的数)
对于询问是否有$x$这个积,直接$O(sqrt(x))$枚举
(额外说一句,lxl在讨论里说了维护商的方法:离线后扫一遍(虽然我没听懂))
1 // luogu-judger-enable-o2 2 #include<cmath> 3 #include<cstdio> 4 #include<cctype> 5 #include<bitset> 6 #include<cstring> 7 #include<algorithm> 8 using namespace std; 9 const int N=100005; 10 struct a 11 { 12 int typ,id; 13 int l,r,v,q,ans; 14 }mo[N]; 15 bitset<N> stat,rsta; 16 int n,m,t1,t2,t3,t4,sqr; 17 int num[N],cnt[N]; 18 inline int read() 19 { 20 int ret=0; 21 char ch=getchar(); 22 while(!isdigit(ch)) 23 ch=getchar(); 24 while(isdigit(ch)) 25 ret=(ret<<3)+(ret<<1)+(ch^48),ch=getchar(); 26 return ret; 27 } 28 bool cmp(a x,a y) 29 { 30 return x.v==y.v?x.r<y.r:x.v<y.v; 31 } 32 bool com(a x,a y) 33 { 34 return x.id<y.id; 35 } 36 inline void change(int val,int typ) 37 { 38 if(typ) 39 { 40 if(++cnt[val]==1) 41 stat[val]=true,rsta[N-val]=true; 42 } 43 else 44 { 45 if(!(--cnt[val])) 46 stat[val]=false,rsta[N-val]=false; 47 } 48 } 49 inline int ask(int typ,int qry) 50 { 51 if(typ==1) return (stat&(stat<<qry)).count(); 52 else if(typ==2) return (stat&(rsta>>(N-qry))).count(); 53 else 54 { 55 register int i; 56 for(i=1;i*i<=qry;i++) 57 if((stat[i]&&stat[qry/i])&&qry%i==0) return true; 58 return false; 59 } 60 } 61 int main() 62 { 63 register int i; 64 n=read(),m=read(),sqr=sqrt(n); 65 for(i=1;i<=n;i++) num[i]=read(); 66 for(i=1;i<=m;i++) 67 { 68 t1=read(),t2=read(),t3=read(),t4=read(); 69 mo[i].typ=t1,mo[i].l=t2,mo[i].r=t3,mo[i].q=t4; 70 mo[i].id=i,mo[i].v=(t2-1)/sqr+1; 71 } 72 sort(mo+1,mo+1+m,cmp); 73 register int lp=1,rp=0; 74 for(i=1;i<=m;i++) 75 { 76 while(lp<mo[i].l) change(num[lp++],0); 77 while(lp>mo[i].l) change(num[--lp],1); 78 while(rp<mo[i].r) change(num[++rp],1); 79 while(rp>mo[i].r) change(num[rp--],0); 80 mo[i].ans=ask(mo[i].typ,mo[i].q); 81 } 82 sort(mo+1,mo+1+m,com); 83 for(i=1;i<=m;i++) 84 mo[i].ans?puts("hana"):puts("bi"); 85 return 0; 86 }