now1每一位表示第i位是否存在,now2 表示 maxn-i位是否存在
1. 差为x , now1左移 x 位和now1做按位与 存在一个 1 则 存在
2. 和为x now1第 i 位存在,则值为 i 存在, 需要找 x - i 是否存在
如何表示 x - i ?
i 存在,maxn - i 存在,则 (maxn - i) - (maxn - x) = x - i
故将 now2 右移 maxn - x 位 与 now1 做按位与运算存在 1 则存在
3.积为x , 枚举 x 因数判断是否存在,复杂度O( sqrt(n) )
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 100005;//O(n*sqrt(n))
struct N{int l,r,id,x,op;}q[maxn];
int ans[maxn],a[maxn],Ans,unit;
int Be[maxn];
bitset<maxn> now1,now2; //每一位表示x是否存在
int num[maxn];//每一位的数量
int cmp(N c,N d){
return Be[c.l]==Be[d.l]? c.r<d.r: c.l<d.l;
}
int cmp2(N c,N d){
return c.id<d.id;
}
void revise(int x,int d){
if(d<0){ num[x]--;if(num[x]==0)now1[x]=0,now2[maxn-x]=0;}
if(d>0){ num[x]++;if(num[x]==1)now1[x]=1,now2[maxn-x]=1;}
}
int main()
{
int n,m,l,r;
scanf("%d%d",&n,&m); unit = sqrt(n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]),Be[i] = i/unit+1;
for(int i=1;i<=m;i++){
scanf("%d %d %d %d",&q[i].op,&q[i].l,&q[i].r,&q[i].x);q[i].id = i;
}
sort(q+1,q+m+1,cmp);
l = 1,r = 0;
for(int i=1;i<=m;i++){
while(l<q[i].l)revise(a[l],-1),l++;
while(l>q[i].l)revise(a[l-1],1),l--;
while(r<q[i].r)revise(a[r+1],1),r++;
while(r>q[i].r)revise(a[r],-1),r--;
int k = q[i].op;
Ans = q[i].x;
switch(k){
case 1:
if((now1&(now1<<Ans)).any()){
ans[q[i].id] = 1;
}else ans[q[i].id] = 0;
break;
case 2:
if((now1&(now2>>(maxn-Ans))).any()){
ans[q[i].id] = 1;
}else ans[q[i].id] = 0;
break;
case 3:for(int j=1;j*j<=Ans;j++){
if(Ans%j==0){
if(now1[j]&&now1[Ans/j]){
ans[q[i].id] = 1;break;
}
}
}
break;
}
}
for(int i=1;i<=m;i++){
printf("%s\n",ans[i]?"hana":"bi");
}
return 0;
}