BZOJ传送门
洛谷传送门
解析:
显然这种存在性问题可以考虑用bitset来解决。
对于乘法直接 O ( c ) O(\sqrt c) O(c)暴力枚举因数就行了。
对于减法,显然我们可以用bitset中的位移来操作一波。
对于加法,我们可以把它转换成减法,设所有 a a a值中的最大值为 c c c。
则对于询问 b b b,如果有解 x + y = b x+y=b x+y=b,则 ( c − x ) − y = c − b (c-x)-y=c-b (c−x)−y=c−b,于是我们维护一个反向的bitset,每次询问两个bitset里面有没有差为 c − b c-b c−b的数就行了。
代码:
#include<bits/stdc++.h>
#define re register
#define gc get_char
#define cs const
namespace IO{
inline char get_char(){
static cs int Rlen=1<<20|1;
static char buf[Rlen],*p1,*p2;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}
inline int getint(){
re char c;
while(!isdigit(c=gc()));re int num=c^48;
while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
return num;
}
}
using namespace IO;
cs int N=1e5+5;
int n,m,a[N];
std::bitset<N> t,B,R;
int bsiz;
int block[N];
struct Query{
int l,r,id,typ,val;
friend bool operator<(cs Query &a,cs Query &b){
return block[a.l]==block[b.l] ? ((block[a.l]&1)?(a.r>b.r):(a.r<b.r)) : block[a.l]<block[b.l];
}
}q[N];
int c,d,cnt[N];
inline void ins(int val){
if(!(cnt[val]++)){
B[val]=1;
R[c-val]=1;
}
}
inline void del(int val){
if(!(--cnt[val])){
B[val]=0;
R[c-val]=0;
}
}
inline bool check(int val,int typ){
switch(typ){
case 1:return (B&(B>>val)).count();
case 2:return (B&(R>>(c-val))).count();
case 3:{
for(int re i=1;i*i<=val;++i)
if(val%i==0&&B[i]&&B[val/i])return true;
return false;
}
}
}
int l=1,r;
bool ans[N];
signed main(){
n=getint(),m=getint();
bsiz=std::max(1.,sqrt((double)n*n/m));
for(int re i=1;i<=n;++i)c=std::max(c,a[i]=getint()),block[i]=i/bsiz;
for(int re i=1;i<=m;++i){
q[i].typ=getint();
q[i].l=getint();
q[i].r=getint();
d=std::max(q[i].val=getint(),d);
q[i].id=i;
}
c=std::max(c,d);
std::sort(q+1,q+m+1);
for(int re i=1;i<=m;++i){
while(r<q[i].r)ins(a[++r]);
while(l>q[i].l)ins(a[--l]);
while(r>q[i].r)del(a[r--]);
while(l<q[i].l)del(a[l++]);
ans[q[i].id]=check(q[i].val,q[i].typ);
}
for(int re i=1;i<=m;++i)puts(ans[i]?"yuno":"yumi");
return 0;
}