BZOJ 4810 [Ynoi2017]由乃的玉米田 ——Bitset 莫队算法
加法和减法的操作都能想到Bitset。
然后发现乘法比较难办,反正复杂度已经是$O(n\log{n})$了
枚举因数也不能更差了,直接枚举就好了。
#include <map> #include <ctime> #include <cmath> #include <queue> #include <bitset> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define F(i,j,k) for (int i=j;i<=k;++i) #define D(i,j,k) for (int i=j;i>=k;--i) #define maxn 100005 bitset <100010> a,b; int T,tot,L[maxn],R[maxn],n,m,c[maxn],bel[maxn]; struct Query{ int l,r,opt,x,id; bool operator < (const Query & a)const { return bel[l]==bel[a.l]?r<a.r:bel[l]<bel[a.l]; } }q[maxn]; void init() { T=sqrt(n); for(int i=1;i<=n;i+=T)L[++tot]=i,R[tot]=i+T-1; R[tot]=n; F(i,1,tot) F(j,L[i],R[i]) bel[j]=i; } int cnt[maxn],ans[maxn]; void add(int x) {cnt[x]++;if(cnt[x]==1)a[x]=1,b[maxn-x]=1;} void dec(int x) {cnt[x]--;if (!cnt[x]) a[x]=0,b[maxn-x]=0;} bool Cha(int x) { if (((a>>x)&a).count()) return true; return false; } bool He(int x) { if (((b>>(maxn-x))&a).count()) return true; return false; } bool Mul(int x) { int lim=sqrt(x+1); F(i,1,lim)if(!(x%i))if (a[i]&&a[x/i]) return true; return false; } int main() { scanf("%d%d",&n,&m);init(); F(i,1,n) scanf("%d",&c[i]); F(i,1,m) { scanf("%d%d%d%d",&q[i].opt,&q[i].l,&q[i].r,&q[i].x); q[i].id=i; } sort(q+1,q+m+1); int l=1,r=0; F(i,1,m) { while (r<=q[i].r) add(c[++r]); while (r>q[i].r) dec(c[r--]); while (l<=q[i].l) dec(c[l++]); while (l>q[i].l) add(c[--l]); switch(q[i].opt) { case 1: if (Cha(q[i].x)) ans[q[i].id]=1; break; case 2: if (He(q[i].x)) ans[q[i].id]=1; break; case 3: if (Mul(q[i].x)) ans[q[i].id]=1; break; } } F(i,1,m) if (ans[i]) printf("yuno\n"); else printf("yumi\n"); }