zoukankan      html  css  js  c++  java
  • 【BZOJ4810】[YNOI2017] 由乃的玉米田(莫队+bitset)

    点此看题面

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

    莫队算法

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

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

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

    关于(bitset)

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

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

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

    它有一个比较常用的函数:(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;
    }
    
  • 相关阅读:
    python计算纹理特征
    遥感影像提取农作物种植分布数据之经验总结
    Python实现多线程调用GDAL执行正射校正
    Centos7.3 编译安装GDAL以及Python的GDAL包
    C#通过COM组件调用IDL的pro程序
    IDL实现矢量文件裁剪栅格数据
    HttpClient使用示列(post请求的)
    SpringBoot自带的定时功能
    mysql安装与启用
    dos命令之端口查看
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/BZOJ4810.html
Copyright © 2011-2022 走看看