洛谷 P3674 小清新人渣的本愿 bitset+莫队

题目:
https://www.luogu.org/problemnew/show/P3674

题目大意:
给你一个长度为 N 的序列,每次询问[l,r]能不能取出两个数,和或差或积等于 C ,记为询问1,2,3。其中 N <= 1 e 5 ,序列中每一个数包括询问中的数 k <= 1 e 5

分析:显然可以用bitset做到 c / 64 的复杂度求两个数是否差为C,加法维护一个反的bitset,乘法直接暴力。可以卡过去,时间复杂度有点玄学。

代码:

// luogu-judger-enable-o2
#include <iostream>
#include <cstdio>
#include <cmath>
#include <bitset>
#include <algorithm>

const int maxn=1e5+7;

using namespace std;

bitset <maxn> A,B;
int a[maxn],b[maxn];
int belong[maxn];
int n,m,l,r;

struct node{
    int l,r,num,op,x,ans;
}q[maxn];

bool cmp1(node x,node y)
{
    if (belong[x.l]==belong[y.l]) return x.r<y.r;
    return x.l<y.l;
}

bool cmp2(node x,node y)
{
    return x.num<y.num;
}

void updata(int x,int c)
{
    if (c==1)
    {
        b[a[x]]++;
        if (b[a[x]]>=1)
        {
            A[a[x]]=1;
            B[maxn-a[x]]=1;
        }
    }
    else
    {
        b[a[x]]--;
        if (b[a[x]]<1)
        {
            A[a[x]]=0;
            B[maxn-a[x]]=0;
        }
    }
}

int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    for (int i=1;i<=m;i++)
    {
        scanf("%d%d%d%d",&q[i].op,&q[i].l,&q[i].r,&q[i].x);
        q[i].num=i;
    }
    int block=trunc(sqrt(n));
    for (int i=1;i<=n;i++) belong[i]=(i-1)/block+1;
    sort(q+1,q+m+1,cmp1);
    l=1; r=1;   
    updata(1,1);    
    for (int i=1;i<=m;i++)
    {
        for (r;r<q[i].r;r++) updata(r+1,1);
        for (r;r>q[i].r;r--) updata(r,-1);
        for (l;l<q[i].l;l++) updata(l,-1);
        for (l;l>q[i].l;l--) updata(l-1,1);
        if (q[i].op==1)
        {
            q[i].ans=((A&(A>>q[i].x)).count());
        }
        if (q[i].op==2)
        {
            q[i].ans=((A&(B>>(maxn-q[i].x))).count());
        }
        if (q[i].op==3)
        {
            q[i].ans=0;
            for (int j=1;j*j<=q[i].x;j++)
            {
                if (q[i].x%j!=0) continue;
                if ((b[j]) && (b[q[i].x/j]))
                {
                    q[i].ans=1;
                    break;
                }
            }
        }
    }
    sort(q+1,q+m+1,cmp2);
    for (int i=1;i<=m;i++)
    {
        if (q[i].ans) printf("hana\n");
                 else printf("bi\n");
    }
}

猜你喜欢

转载自blog.csdn.net/liangzihao1/article/details/80900664