【题解】Luogu P3674 小清新人渣的本愿

原题传送门

这题还算简单(我记得我刚学oi时就来写这题,然后暴力都爆零了)

看见无修改,那么这题应该是莫队

维护两个bitset,第二个是第一个的反串,bitset内维护每个数字是否出现过

第一种操作:

要求y-z=x,所以y=z+x

最后判断有没有k和k-x都出现在bitset中的情况

第二种操作:

和第一种类似的方法,就不再讲了qwqwq

第三种操作:

暴力把x分解成两个数的乘积,判断这两个数是否出现过

因为莫队是\(O(n \sqrt n)\)的,查询\(O(\frac{mN}{\omega})\)

#include <bits/stdc++.h>
#define N 100005
#define getchar nc
using namespace std;
inline char nc(){
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
    register int x=0,f=1;register char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return x*f;
}
inline void write(register int x)
{
    if(!x)putchar('0');if(x<0)x=-x,putchar('-');
    static int sta[20];register int tot=0;
    while(x)sta[tot++]=x%10,x/=10;
    while(tot)putchar(sta[--tot]+48);
}
struct query{
    int k,l,r,x,id,bl;
}q[N];
inline bool cmp(register query a,register query b)
{
    return a.bl!=b.bl?a.l<b.l:((a.bl&1)?a.r<b.r:a.r>b.r);
}
int n,m,blocksize=0,v[N],sum[N],ans[N];
bitset <N> dl1,dl2;
inline void add(register int x)
{
    if(++sum[v[x]]==1)
        dl1[v[x]]=1,dl2[N-v[x]]=1;
}
inline void del(register int x)
{
    if(--sum[v[x]]==0)
        dl1[v[x]]=0,dl2[N-v[x]]=0;
}
int main()
{
    n=read(),m=read();
    blocksize=sqrt(n);
    for(register int i=1;i<=n;++i)
        v[i]=read();
    for(register int i=1;i<=m;++i)
        q[i].k=read(),q[i].l=read(),q[i].r=read(),q[i].x=read(),q[i].id=i,q[i].bl=(q[i].l-1)/blocksize+1;
    sort(q+1,q+1+m,cmp);
    int l=1,r=0;
    dl1.reset(),dl2.reset();
    for(register int i=1;i<=m;++i)
    {
        int ll=q[i].l,rr=q[i].r;
        while(l>ll)
            add(--l);
        while(r<rr)
            add(++r);
        while(l<ll)
            del(l++);
        while(r>rr)
            del(r--);
        int k=q[i].k,x=q[i].x,id=q[i].id;
        if(k==1)
        {
            if((dl1&(dl1<<x)).any())
                ans[id]=1;	
        }
        else if(k==2)
        {
            if((dl1&(dl2>>(N-x))).any())
                ans[id]=1;
        }
        else
        {
            for(register int j=1;j*j<=x;++j)
                if(!(x%j))
                    if(dl1[j]&&dl1[x/j])
                    {
                        ans[id]=1;
                        break;
                    }
        }
    }
    for(register int i=1;i<=m;++i)
        puts(ans[i]?"hana":"bi");
    return 0;
}
posted @ 2019-02-09 10:55  JSOI爆零珂学家yzhang  阅读(384)  评论(0编辑  收藏  举报