BZOJ---4810:[Ynoi2017]由乃的玉米田【莫队+bitset】

该博客介绍了BZOJ 4810题目,主要探讨如何使用离线后的莫队算法和bitset来解决区间内寻找两个数之差、和、积等于特定值的问题。博主分析了针对三种情况的不同处理方法,并提供了相应的代码实现。
摘要由CSDN通过智能技术生成

题面:

BZOJ---4810

题意:

给定一个序列,每次查询一个区间的三种情况:(1)是否有两数之差为X(2)是否有两数之和为X(3)是否有两数之积为X

分析:

容易想到离线后莫队,考虑该怎么维护答案;对于①操作:A - B = X   ----> A  = B + X,对于一个集合都加上X,用bitset维护区间的数的集合S,只需要判断 S&(S<<X)即可,对于②:A + B = X  ---->  A = -B + X,但bitset不能维护负数,索性再维护(N-B)的集合T,那么有:A - (N-B) = X - N ---> A+(N-X) = (N-B),只需判断(S<<(N-X))&T 即可;对于三操作,直接暴力分解因子判断即可

代码:

#include <bits/stdc++.h>
 
using namespace std;
const int maxn = 1e5+15;
struct node{
    int op,l,r,x,pos;
}p[maxn];
int n,m,block,a[maxn],num[maxn],ans[maxn];
bool cmp(node a,node b){
    return a.l/block==b.l/block?a.r<b.r:a.l<b.l;
}
bitset<maxn> bs1,bs2,s;
inline void add(int x){
    bs1[a[x]] = 1;
    bs2[maxn-1-a[x]] = 1;
    num[a[x]]++;
}
inline void del(int x){
    if(--num[a[x]]==0){
        bs1[a[x]] = 0;
        bs2[maxn-1-a[x]] = 0;
    }
}
int main(){
    cin >> n >> m;
    block = sqrt(n*1.0);
    for(int i = 1;i <= n; ++i) cin >> a[i];
    for(int i = 0;i < m; ++i) cin>>p[i].op>>p[i].l>>p[i].r>>p[i].x,p[i].pos=i;
    sort(p,p+m,cmp);
    int L = 1,R = 0;
    for(int i = 0;i < m; ++i){
         while(R < p[i].r) ++R,add(R);
         while(R > p[i].r) del(R),--R;
         while(L < p[i].l) del(L),++L;
         while(L > p[i].l) --L,add(L);
         if(p[i].op == 1){
            s = (bs1<<p[i].x)&bs1;
            if(s.any()) ans[p[i].pos] = 1;
         }
         else if(p[i].op == 2){
            s = (bs1<<(maxn-1-p[i].x))&bs2;
            if(s.any()) ans[p[i].pos] = 1;
         }
         else{
            for(int j = 1;j*j<=p[i].x; ++j){
                if(p[i].x%j==0&&num[j]&&num[p[i].x/j]){
                   ans[p[i].pos] = 1;
                   break;
                }
            }
         }
    }
    for(int i = 0;i < m; ++i){
        if(ans[i]) puts("yuno");
        else puts("yumi");
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值