bzoj4810 [ YNOI2017 ] -- 莫队+bitset

来源:互联网 发布:易语言视频解析源码 编辑:程序博客网 时间:2024/06/17 07:55

莫队。维护2bitset,第一个记录数字是否出现,第二个是第一个翻转后的结果。那么查询差时将第一个左移x位再与原来的and一下;查询和时将第一个与第二个左移maxx的结果and一下;查询积时枚举每个因数就可以了。
时间复杂度O(nn+n232)

代码:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<bitset>#include<cmath>using namespace std;#define N 100010bitset<N>f,g,t;struct Node{    int l,r,p,f,x;}c[N];int i,j,k,n,m,x,a[N],b[N],s,l,r,Cnt[N],M;bool Ans[N];inline bool Cmp(Node x,Node y){    return b[x.l]<b[y.l]||(b[x.l]==b[y.l]&&x.r<y.r);}inline void Update1(int x){    if(++Cnt[x]==1)f[x]=g[M-x]=1;}inline void Update2(int x){    if(!(--Cnt[x]))f[x]=g[M-x]=0;}inline bool Query(int x,int y){    if(x==1){        t=f&(f>>y);        return t.count();    }    if(x==2){        t=f&(g>>(M-y));        return t.count();    }    s=sqrt((double)y);    for(int i=1;i<=s;i++)    if(!(y%i)&&f[i]&&f[y/i])return 1;    return 0;}inline int Max(int x,int y){    return x<y?y:x;}int main(){    scanf("%d%d",&n,&m);    for(i=1;i<=n;i++)scanf("%d",&a[i]),M=Max(M,a[i]);    for(i=1;i<=m;i++)scanf("%d%d%d%d",&c[i].p,&c[i].l,&c[i].r,&c[i].x),c[i].f=i,M=Max(M,c[i].x);    s=sqrt((double)n);    for(i=1;i<=n;i++)b[i]=(i-1)/s+1;    sort(c+1,c+n+1,Cmp);    for(l=i=1;i<=n;i++){        while(c[i].l<l)Update1(a[--l]);        while(c[i].r>r)Update1(a[++r]);        while(c[i].l>l)Update2(a[l++]);        while(c[i].r<r)Update2(a[r--]);        Ans[c[i].f]=Query(c[i].p,c[i].x);    }    for(i=1;i<=n;i++)if(Ans[i])printf("yuno\n");else printf("yumi\n");    return 0;}
原创粉丝点击