【BZOJ 4810】【YNOI 2017】由乃的玉米田【莫队+bitset】

来源:互联网 发布:网络剧小心超人与伽罗 编辑:程序博客网 时间:2024/06/05 00:46

Description

给你一个序列a,长度为n,有m次操作,每次询问一个区间是否可以选出两个数它们的差为x,或者询问一个区间是否可以选出两个数它们的和为x,或者询问一个区间是否可以选出两个数它们的乘积为x ,这三个操作分别为操作1,2,3选出的这两个数可以是同一个位置的数

Solution

  一开始直接想到的是莫队,但莫队归莫队,怎么处理这三个操作呢?看看了大神题解,又听了一番同市神犇的指点,终于学会了一点bitset的应用。
  
  对bitset的学习,可以参考这篇:传送
  
  用bitset维护每个值是否出现,再用一个s数组来保存这个值出现了几次,这样维护一下就好了。
  
  乘法操作,直接通过n12的方法判断即可。
  
  减法操作,相当于是查询是否存在ii,jj满足a[i]a[j]=x的形式,那么把bitset右移x位与原来的&一下看新的二进制数是否为0(用bitset自带的count就好了)
  
  加法类似,不过需要维护的是a[i]+a[j]=x的形式,那么我用cc是所有数中的最大值)去减a[j],即变成a[i]=(ca[j])+xc的形式,另外维护一个bitset,右移(cx)位查询就好了。
  复杂度O(n32+n232)

Code

#include<cstdio>#include<cstring>#include<algorithm>#include<bitset>#include<cmath>#include<iostream>using namespace std;const int N = 100010;bitset<N> f,g;int a[N],ans[N],pos[N],s[N];int n,m;struct node{int id,o,l,r,x;}qu[N];inline bool cmp(node a,node b) {    return pos[a.l] == pos[b.l] ? a.r < b.r : pos[a.l] < pos[b.l];}int main(){    scanf("%d%d",&n,&m);    int bs = (int)sqrt(n);    for(int i = 1;i <= n;i++) {        scanf("%d",&a[i]);        pos[i] = (i-1)/bs;    }    for(int i = 1;i <= m;i++) {        scanf("%d%d%d%d",&qu[i].o,&qu[i].l,&qu[i].r,&qu[i].x);        qu[i].id = i;    }    sort(qu+1,qu+m+1,cmp);    int pl = 1,pr = 0;    memset(s,0,sizeof(s));    for(int i = 1;i <= m;i++)    {        if(qu[i].l == qu[i].r){ans[qu[i].id] = 0;continue;}        if(pr < qu[i].r)            for(int j = pr+1;j <= qu[i].r;j++) {                s[a[j]]++; f[a[j]]=1; g[N-a[j]]=1;            }        else            for(int j = pr;j > qu[i].r;j--) {                s[a[j]]--;                if(!s[a[j]]){f[a[j]]=0;g[N-a[j]]=0;}            }        pr = qu[i].r;        if(pl < qu[i].l)            for(int j = pl;j < qu[i].l;j++) {                s[a[j]]--;                if(!s[a[j]]){f[a[j]]=0;g[N-a[j]]=0;}            }        else            for(int j = pl-1;j >= qu[i].l;j--) {                s[a[j]]++; f[a[j]]=1; g[N-a[j]]=1;            }        pl = qu[i].l;        if(qu[i].o == 1)            ans[qu[i].id] = ((f>>qu[i].x)&f).any();        if(qu[i].o == 2)            ans[qu[i].id] = ((g>>(N-qu[i].x))&f).any();        if(qu[i].o == 3) {            if(qu[i].x == 0 && f[0])                ans[qu[i].id] = 1;            for(int j = 1;j*j<=qu[i].x;j++)                if(!(qu[i].x%j))                    if(f[j]&f[qu[i].x/j]) {                        ans[qu[i].id] = 1;                        break;                    }        }    }    for(int i = 1;i <= m;i++)        printf(ans[i] ? "yuno\n" : "yumi\n");    return 0;}
1 0
原创粉丝点击