【BZOJ4810】[YNOI2017] 由乃的玉米田(莫队+bitset)

本文介绍如何使用莫队算法和bitset解决区间查询问题,通过实例讲解差、和、积的快速判断方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

点此看题面

大致题意: 给你一段序列,每次询问一段区间内是否存在两个数的差或和或积为\(x\)

莫队算法

看到区间询问+可以离线,首先想到了莫队啊。

但是,在较短的时间内更新信息依然比较难以实现。

于是,我们就要考虑用\(bitset\)了。

关于\(bitset\)

这应该是我第一次使用\(bitset\)吧,所以简单介绍一下它的使用方式。

其作用就相当于存储一个特别大的二进制数。可以把它看成一个\(bool\)数组来使用。

它的好处就在于,它可以直接进行\(\&,|,\text{^},<<,>>\)等各种位运算操作。

它有一个比较常用的函数:\(any()\),用于判断该\(bitset\)是否有某个元素值为\(1\)

另外,还有一个函数\(count()\)是统计有几个\(1\)

实际上,了解了这些,我们就可以用\(bitset\)来做这题了。

大致思路

考虑开两个\(bitset\)\(s1\)\(s2\),其中\(s1_i\)表示值为\(i\)的元素是否存在,\(s2_i\)表示值为\(N-i\)的元素是否存在。

这样一来,似乎就不难处理差值的操作了,答案就是\((s1\&(s1<<x)).any()\),这还是比较好理解的,即判断是否有一个数和比它大\(x\)的数同时存在。

同理可得,和的操作答案就是\((s1\&(s2>>N-x)).any()\)

对于积的操作就略麻烦了一点,需要枚举因数\(j\),然后判断\(j\)\(\frac xj\)是否同时存在即可,这个操作是\(O(\sqrt x)\)的。

具体实现可见代码。

代码

#include<bits/stdc++.h>
#define N 100000
#define abs(x) ((x)<0?-(x):(x))
using namespace std;
int n,query_tot,a[N+5];
class Class_FIO
{
    private:
        #define Fsize 100000
        #define tc() (A==B&&(B=(A=Fin)+fread(Fin,1,Fsize,stdin),A==B)?EOF:*A++)
        char ch,*A,*B,Fin[Fsize];
    public:
        Class_FIO() {A=B=Fin;}
        inline void read(int &x) {x=0;while(!isdigit(ch=tc()));while(x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc()));}
}F;
class Class_CaptainMotao//莫队
{
    private:
        int block_size,ans[N+5],cnt[N+5];bitset<N+5> s1,s2;
        inline void Add(int x) {if(!cnt[a[x]]++) s1[a[x]]=s2[N-a[x]]=1;}//新加一个元素
        inline void Del(int x) {if(!--cnt[a[x]]) s1[a[x]]=s2[N-a[x]]=0;}//删除一个元素
    public:
        struct Query
        {
            int l,r,val,op,pos,bl;
            inline friend bool operator < (Query x,Query y) {return x.bl^y.bl?x.bl<y.bl:(x.bl&1?x.r<y.r:x.r>y.r);}
        }q[N+5];
        inline void Solve()
        {
            int i,j,L=1,R=0;
            for(block_size=sqrt(n),i=1;i<=query_tot;++i) F.read(q[i].op),F.read(q[i].l),F.read(q[i].r),F.read(q[i].val),q[q[i].pos=i].bl=(q[i].l-1)/block_size+1;//读入
            for(L=1,R=0,sort(q+1,q+query_tot+1),i=1;i<=query_tot;++i)
            {
                while(R<q[i].r) Add(++R);while(L>q[i].l) Add(--L);while(R>q[i].r) Del(R--);while(L<q[i].l) Del(L++);
                switch(q[i].op)
                {
                    case 1:ans[q[i].pos]=(s1&(s1<<q[i].val)).any();break;//对于差的操作
                    case 2:ans[q[i].pos]=(s1&(s2>>N-q[i].val)).any();break;//对于和的操作
                    case 3:for(j=1;1LL*j*j<=q[i].val&&!ans[q[i].pos];++j) !(q[i].val%j)&&s1[j]&&s1[q[i].val/j]&&(ans[q[i].pos]=1);break;//对于积的操作
                }
            }
            for(i=1;i<=query_tot;++i) puts(ans[i]?"yuno":"yumi");//输出答案
        }
}C;
int main()
{
    register int i;
    for(F.read(n),F.read(query_tot),i=1;i<=n;++i) F.read(a[i]);
    return C.Solve(),0;
}

转载于:https://www.cnblogs.com/chenxiaoran666/p/BZOJ4810.html

资源下载链接为: https://pan.quark.cn/s/9e7ef05254f8 在网页设计中,为图片添加文字是一种常见的需求,用于增强视觉效果或传达更多信息。本文将介绍两种常用的方法:一种是将图片设置为背景并添加文字;另一种是利用<span>标签结合CSS定位来实现。 这种方法通过CSS实现,将图片设置为一个容器(通常是<div>)的背景,然后在容器中添加文字。具体步骤如下: 创建一个包含文字的<div>元素: 使用CSS设置<div>的背景图片,并调整其尺寸以匹配图片大小: 如有需要,可使用background-position属性调整图片位置,确保文字显示在合适位置。这样,文字就会显示在图片之上。 另一种方法是将文字放在<span>标签内,并通过CSS绝对定位将其放置在图片上。步骤如下: 创建一个包含图片和<span>标签的<div>: 设置<div>为相对定位,以便内部元素可以相对于它进行绝对定位: 设置<span>为绝对定位,并通过调整top和left属性来确定文字在图片上的位置: 这种方法的优点是可以精确控制文字的位置,并且可以灵活调整文字的样式,如颜色和字体大小。 两种方法各有优势,可根据实际需求选择。在实际开发中,还可以结合JavaScript或jQuery动态添加文字,实现更复杂的交互效果。通过合理运用HTML和CSS,我们可以在图片上添加文字,创造出更具吸引力的视觉效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值