这题带我进入了bitset的大门QwQ
在学bitset之前,我的莫队完全不知道怎么出解。。
然后去膜了几个大佬,大佬们都是用bitset
于是就补了一发。。
bitset学习
有bitset出解就好办了。。
+和-就用两个bitset就好,正着一个反着一个
然后成绩就暴力枚举就好了。。
时间复杂度据说是
O(nsqrtn+n∗n/32)
但其实感觉还是挺慢的,但30s的题,就凑合一下吧
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include <bitset>
using namespace std;
bitset <100010> a,b;
const int N=100005;
const int MAX=100005;
int n,m,nn;
int A[N];
int belong[N];
struct qq{int id,op,l,r,x;}s[N];
bool cmp (qq a,qq b)
{
return belong[a.l]==belong[b.l]?a.r<b.r:belong[a.l]<belong[b.l];
}
bool ok[N];
int cnt[N];//这个数字出现了多少次
void add (int x)
{
cnt[x]++;
if (cnt[x]==1) a[x]=1,b[MAX-x]=1;
}
void del (int x)
{
cnt[x]--;
if (cnt[x]==0) a[x]=0,b[MAX-x]=0;
}
bool cha (int x)//是否存在差为x
{
return ((a>>x)&a).any();
}
bool he(int x)
{
return ((b>>(MAX-x))&a).any();
}
bool Mul (int x)
{
for (int u=1;u*u<=x;u++)
{
if (x%u==0&&a[u]>0&&a[x/u]>0)
return true;
}
return false;
}
int main()
{
scanf("%d%d",&n,&m);
nn=sqrt(n);
for (int u=1;u<=n;u++) belong[u]=(u-1)/nn+1;
for (int u=1;u<=n;u++) scanf("%d",&A[u]);
for (int u=1;u<=m;u++)
{
scanf("%d%d%d%d",&s[u].op,&s[u].l,&s[u].r,&s[u].x);
s[u].id=u;
}
sort(s+1,s+1+m,cmp);
memset(ok,false,sizeof(ok));
int l=1,r=0;
for (int u=1;u<=m;u++)
{
while (r<s[u].r) add(A[++r]);
while (r>s[u].r) del(A[r--]);
while (l<s[u].l) del(A[l++]);
while (l>s[u].l) add(A[--l]);
if (s[u].op==1) //差为x
ok[s[u].id]=cha(s[u].x);
if (s[u].op==2)
ok[s[u].id]=he(s[u].x);
if (s[u].op==3)
ok[s[u].id]=Mul(s[u].x);
}
for (int u=1;u<=m;u++)
if (ok[u]) printf("yuno\n");
else printf("yumi\n");
return 0;
}