luogu-P3674

题目链接:https://www.luogu.org/problem/P3674
题目大意:给出一个序列,然后给出一些区间,询问在这些区间中是否存在两个数可以相加等于x,相减等于x,相乘等于x,如果有,那么我们就输出"hana",否则就输出"bi"。
解法:这里我们很容易的会想到莫队算法来记录其中的数字出现的次数,然后遍历一遍去寻找可能满足的数字,这里可能会T,因为莫队算法是采用分块思维的暴力算法,时间复杂度为O(N*len),这里的len是分块的长度,所以如果在每个m中再加一个O(n)的复杂度,那基本上就炸了,所以这里我们可以采用bitset优化一下,bitset是一种二进制的容器,在这里,它的每一位都可以看做是一个数的状态(存在或不存在)。
对于z+y=x存在的话,那么我们可以看做存在z=x-y,对于z-y=x存在的话,我们可以看做存在z=x+y,减法的时候我们很好寻找到x+y是否存在,那么我们要怎样去寻找x-y的状态呢?
我们先设y1=N-y,那么z=x-y=>z=x-(N-y1)=>z=y1+x-N,那么我们用一个bitset来存y1的状态,然后我们在加上x-n不就行了吗?
代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+7;
void read(int &x)
{
    char c;
    int f=1;
    x=0;
    c=getchar();
    while(c<'0' || c>'9'){
        if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0' && c<='9'){
        x=x*10+c-'0';
        c=getchar();
    }
    //return x*f;
}
bitset<maxn> now1,now2;
struct node
{
    int l,r,pos,id,k,x;
    bool operator <(node a)const{
        return pos==a.pos?r<a.r:pos<a.pos;
    }
}q[maxn];
int c[maxn],a[maxn],ans[maxn];
void add(int x){if(++c[x]==1)now1[x]=1,now2[maxn-7-x]=1;}
void del(int x){if(--c[x]==0)now1[x]=0,now2[maxn-7-x]=0;}
int main()
{
    int n,m,len;
    read(n),read(m);
    len=sqrt(n);
    for(int i=1;i<=n;i++){
        read(a[i]);
    }
    for(int i=1;i<=m;i++){
        int l,r,k,x;
        read(k),read(l),read(r),read(x);
        q[i]=node{l,r,(l-1)/len+1,i,k,x};
    }
    sort(q+1,q+1+m);
    int l=0,r=0;
    for(int i=1;i<=m;i++){
        while(l<q[i].l){
            del(a[l++]);
        }
        while(l>q[i].l){
            add(a[--l]);
        }
        while(r>q[i].r){
            del(a[r--]);
        }
        while(r<q[i].r){
            add(a[++r]);
        }
        int k=q[i].k,x=q[i].x;
        switch(k){
        case 1:
            ans[q[i].id]=(now1&(now1<<x)).any();
            break;
        case 2:
            ans[q[i].id]=(now1&(now2>>(maxn-x-7))).any();
            break;
        case 3:
            for(int j=1;j*j<=x;++j){
                if(x%j)continue;
                if(now1[j]&&now1[x/j]){
                    ans[q[i].id]=1;break;
                }
            }
            break;
        }
    }
    for(int i=1;i<=m;i++){
        ans[i]?printf("hana\n"):printf("bi\n");
    }
    return 0;
}
发布了34 篇原创文章 · 获赞 3 · 访问量 257

猜你喜欢

转载自blog.csdn.net/qq_44641782/article/details/103181927