前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >BZOJ4810: [Ynoi2017]由乃的玉米田(莫队+bitset)

BZOJ4810: [Ynoi2017]由乃的玉米田(莫队+bitset)

作者头像
attack
发布2018-04-13 16:09:33
7100
发布2018-04-13 16:09:33
举报
文章被收录于专栏:数据结构与算法

Description

由乃在自己的农田边散步,她突然发现田里的一排玉米非常的不美。这排玉米一共有N株,它们的高度参差不齐。

由乃认为玉米田不美,所以她决定出个数据结构题

这个题是这样的:

给你一个序列a,长度为n,有m次操作,每次询问一个区间是否可以选出两个数它们的差为x,或者询问一个区间是

否可以选出两个数它们的和为x,或者询问一个区间是否可以选出两个数它们的乘积为x ,这三个操作分别为操作1

,2,3选出的这两个数可以是同一个位置的数

Input

第一行两个数n,m

后面一行n个数表示ai

后面m行每行四个数opt l r x

opt表示这个是第几种操作,l,r表示操作的区间,x表示这次操作的x

定义c为每次的x和ai中的最大值,ai >= 0,每次的x>=2n,m,c <= 100000

Output

对于每个询问,如果可以,输出yuno,否则输出yumi

Sample Input

5 5 1 1 2 3 4 2 1 1 2 1 1 2 2 3 1 1 1 3 5 5 16 1 2 3 4

Sample Output

yuno yumi yuno yuno yumi

HINT

Source

By 佚名提供

一看是lxl的题,再一看不带修改,基本上莫队跑不了了、

这道题我们需要维护每个数出现的情况,因此不难想到bitset,但是bitset是一个01序列,并不能维护一个数出现多次的情况

因此我们还需要一个数组来记录每个数出现的次数

对于减法操作,我们需要找的是a[j]-a[i]=x,那么把bitset右移x位再&一下就好

对于加法操作,我们记录下整个序列的反序列(就是用一个大数减去每一个数后所得的序列),这样我们把翻转后的序列右移后与原序列&一下就好

对于乘法操作,bitset肯定是搞不了了,那么我们暴力判断即可QWQ.... 

时间复杂度O(\frac{n^2}{32})

反思一下自己没做出来的原因:在考虑bitset维护加法操作的时候并没有想到用原序列翻转的性质去搞,然后乘法操作也没想到,就连cnt数组要不要加都考虑了半天QWQ...自己还是太菜了。

代码语言:javascript
复制
#include<cstdio>
#include<cstring>
#include<bitset>
#include<cmath>
#include<algorithm>
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<23,stdin),p1==p2)?EOF:*p1++)
char buf[1<<23],*p1=buf,*p2=buf;
using namespace std;
const int MAXN=1e5+10;
const int limit=100000;
inline int read()
{
    char c=getchar();int x=0,f=1;
    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;
}
int N,M,block;
int belong[MAXN],cnt[MAXN],out[MAXN];
bitset<100001>bit,bitinv;
struct Qus
{
    int l,r,val,opt,ID;
}Q[MAXN];
int a[MAXN];
inline int comp(const Qus &a,const Qus &b)
{
    return belong[a.l]==belong[b.l]?a.r<b.r:belong[a.l]<belong[b.l];
}
inline void Delet(int x)
{
    cnt[x]--;
    if(cnt[x]==0) bit[x]=0,bitinv[limit-x]=0;
}
inline void Add(int x)
{
    cnt[x]++;
    if(cnt[x]==1) 
        bit[x]=1,bitinv[limit-x]=1;
}
inline int Query(int opt,int x)
{
    if(opt==1)//差 
        return ( ((bit>>x) & bit ).any() )?1:0; 
    if(opt==2)
        return ( bit & (bitinv>>(limit-x)) ).any()?1:0;
    if(opt==3)
    {
        if(x==0&&bit[0]) return 1;
        for(int i=1;i*i<=x;i++)
        {
            if(x%i!=0) continue;
            if(bit[i]&&bit[x/i]) return 1;
        }
        return 0;
    }
}
inline void Modui()
{
    sort(Q+1,Q+M+1,comp);
    cnt[0]=1;
    int l=0,r=0,tot=0;
    for(int i=1;i<=M;i++)
    {
        while(l<Q[i].l) Delet(a[l++]),tot++;
        while(l>Q[i].l) Add(a[--l]),tot++;
        while(r<Q[i].r) Add(a[++r]),tot++;
        while(r>Q[i].r) Delet(a[r--]),tot++;
        out[Q[i].ID]=Query(Q[i].opt,Q[i].val);
    }
    //printf("%d\n",tot);
    for(int i=1;i<=M;i++)
        puts(out[i]?"yuno":"yumi");
}
int main()
{
    //freopen("a.in","r",stdin);
    //freopen("b.out","w",stdout);
    N=read();M=read();
    block=sqrt(N);
    for(int i=1;i<=N;i++) a[i]=read(),belong[i]=(i-1)/block+1;
    for(int i=1;i<=M;i++)
    {
        int how=read(),ll=read(),rr=read(),x=read();
        Q[i].opt=how;
        Q[i].l=ll; Q[i].r=rr;
        Q[i].val=x;
        Q[i].ID=i;
    }
    Modui();
    return 0;
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-04-03 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Description
  • Input
  • Output
  • Sample Input
  • Sample Output
  • HINT
  • Source
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档