zoukankan      html  css  js  c++  java
  • BZOJ 4810 [Ynoi2017]由乃的玉米田(莫队+bitset)

    【题目链接】 http://www.lydsy.com/JudgeOnline/problem.php?id=4810

    【题目大意】

      给出一个数列,有三种区间查询,
      分别查询区间是否存在两个数乘积为x,是否存在两个数和为x,以及是否存在两个数差为x,

    【题解】

      我们对于询问进行莫队处理,保存当前区间的权值数组,记为F,
      同时保存权值数组的反向数组G
      那么存在差为x的情况只要存在一组F[i]&F[i-x]=1即可
      存在和为x的情况只要存在一组F[i]&G[M-x+i]即可。
      对于乘积为x的情况,我们枚举x的约数,判断F[i]&F[x/i]是否存在。
      复杂度O(nsqrt(n)+nm/w)

    【代码】

    #include <cstdio>
    #include <algorithm>
    #include <bitset>
    #include <cmath>
    using namespace std;
    const int N=100010,M=100000;
    int limit,n,m,pos[N],a[N],ans[N],cnt[N];
    bitset<N> F,G;
    struct Q{
        int l,r,x,id,op;
        friend bool operator < (const Q &a,const Q &b){
            return pos[a.l]<pos[b.l]||(pos[a.l]==pos[b.l]&&a.r<b.r);
        }
    }ask[M];
    int read(int &x){
        int f=1;char ch=getchar();x=0;
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        x*=f;
    }
    int main(){
        read(n); read(m);
        limit=(int)sqrt(n+0.5);
        for(int i=1;i<=n;i++)read(a[i]),pos[i]=(i-1)/limit+1;
        for(int i=1;i<=m;i++)read(ask[i].op),read(ask[i].l),read(ask[i].r),read(ask[i].x),ask[i].id=i;
        sort(ask+1,ask+m+1);
        for(int i=1,l=1,r=0;i<=m;i++){
            for(;r<ask[i].r;r++)cnt[a[r+1]]++,F.set(a[r+1]),G.set(M-a[r+1]);
            for(;l>ask[i].l;l--)cnt[a[l-1]]++,F.set(a[l-1]),G.set(M-a[l-1]);
            for(;l<ask[i].l;l++){cnt[a[l]]--;if(!cnt[a[l]])F.reset(a[l]),G.reset(M-a[l]);}
            for(;r>ask[i].r;r--){cnt[a[r]]--;if(!cnt[a[r]])F.reset(a[r]),G.reset(M-a[r]);}
            if(ask[i].op==1){if((F&(F>>ask[i].x)).any())ans[ask[i].id]=1;}
            else if(ask[i].op==2){if((F&(G>>(M-ask[i].x))).any())ans[ask[i].id]=1;}
            else{
                for(int j=1;j*j<=ask[i].x;j++)if(ask[i].x%j==0){
                    if(F[j]&F[ask[i].x/j]){ans[ask[i].id]=1;break;}
                }
            }
        }for(int i=1;i<=m;i++)puts(ans[i]?"yuno":"yumi");
        return 0;
    }
  • 相关阅读:
    矩阵旋转
    clang-format 规范及 Visual Stido Code 自定义格式化代码风格
    Windows 安装 MinGW-w64
    Linux配置Visual Stdio Code
    Ubuntu中安装eclipse
    Ubuntu安装JDK11
    Ubuntu安装搜狗输入法
    C/C++算术运算(类型使用)的注意事项
    闰年判断与日期计算
    查看变量类型
  • 原文地址:https://www.cnblogs.com/forever97/p/bzoj4810.html
Copyright © 2011-2022 走看看