给你一个序列a,长度为n,有m次操作,每次询问一个区间是否可以选出两个数它们的差为x,或者询问一个区间是否可以选出两个数它们的和为x,或者询问一个区间是否可以选出两个数它们的乘积为x ,这三个操作分别为操作1,2,3
对于操作3,我们可以很容易通过枚举约数得到。
离线操作,考虑莫队
对于操作1,询问实际上问的就是区间是否存在a和x-a,因为数据范围较小,用bitset维护每个值
对于操作2,考虑一个较大值
m
a
x
n
maxn
maxn ,根据
(
m
a
x
n
−
i
)
−
(
m
a
x
n
−
k
)
=
(
k
−
i
)
(maxn-i)-(maxn-k)=(k−i)
(maxn−i)−(maxn−k)=(k−i),维护
m
a
x
n
−
a
[
i
]
maxn-a[i]
maxn−a[i]即可
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
#define de(c) cout << #c << " = " << c << endl
#define dd(c) cout << #c << " = " << c << " "
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
mt19937 mrand(random_device{}());
const ll mod=1000000007;
int rnd(int x) { return mrand() % x;}
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int maxn = 1e5+50;
bitset<maxn+50> s1,s2;
struct query { int L, R, id,op,val; } q[maxn];
int ans[maxn+50];
int a[maxn+50];
int cnt[maxn+50];
int n,m,unit;
void add(int x)
{
cnt[a[x]]++;
if(cnt[a[x]] == 0)
s1[a[x]] = s2[maxn-a[x]] = cnt[a[x]];
else
s1[a[x]] = s2[maxn-a[x]] = 1;
}
void del(int x)
{
cnt[a[x]]--;
if(cnt[a[x]] == 0)
s1[a[x]] = s2[maxn-a[x]] = cnt[a[x]];
else
s1[a[x]] = s2[maxn-a[x]] = 1;
}
void solve(query node[], int m)
{
memset(ans, 0, sizeof(ans));
s1.reset();
s2.reset();
memset(cnt, 0, sizeof(cnt));
sort(node+1, node + m+1, [](query a, query b) {
if(a.L / unit == b.L / unit)
{
return a.R < b.R;
}
return a.L < b.L;
});
// rep(i,1,m+1)
// {
// dd(node[i].L),dd(node[i].R),dd(node[i].id),dd(node[i].op),de(node[i].val);
// }
int L = 1, R = 0;
for (int i = 1; i < m+1; i++)
{
while (node[i].L > L) del(L++);
while (node[i].L < L) add(--L);
while (node[i].R > R) add(++R);
while (node[i].R < R) del(R--);
// dd(L),de(R);
if(node[i].op == 1)
{
ans[node[i].id] = (s1&(s1<<node[i].val)).any();
}
else if(node[i].op == 2)
{
ans[node[i].id] = (s1&(s2>>(maxn-node[i].val))).any();
}
else
{
for(int j=1;j*j<=node[i].val;j++)
if(node[i].val % j ==0)
{
// de(s1[4]);
if(s1[j] && s1[node[i].val/j])
{
ans[node[i].id]=1;
}
}
}
// ans[node[i].id] = tmp;
}
}
int main(int argc, char const *argv[])
{
ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> n >> m;
unit = int(sqrt(n)+0.5);
rep(i,1,n+1)
{
cin >> a[i];
}
int op,l,r,x;
rep(i,1,m+1)
{
cin >> op >> l >> r >> x;
q[i].op = op;
q[i].L = l;
q[i].R = r;
q[i].val = x;
q[i].id = i;
}
solve(q,m);
rep(i,1,m+1)
{
if(ans[i])
{
cout << "hana"<<endl;
}
else
{
cout << "bi" << endl;
}
}
return 0;
}
/*
node[i].L = 1 node[i].R = 1 node[i].id = 1 node[i].op = 2 node[i].val = 2
node[i].L = 1 node[i].R = 1 node[i].id = 3 node[i].op = 3 node[i].val = 1
node[i].L = 1 node[i].R = 2 node[i].id = 2 node[i].op = 1 node[i].val = 2
node[i].L = 2 node[i].R = 3 node[i].id = 5 node[i].op = 1 node[i].val = 4
node[i].L = 5 node[i].R = 5 node[i].id = 4 node[i].op = 3 node[i].val = 16
*/