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");
}

  

posted @ 2017-04-20 09:02  SfailSth  阅读(220)  评论(0编辑  收藏  举报