ccz181078

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: :: 管理 ::

用莫队求出每个询问区间对应的bitset(表示每个权值是否出现过),对于加减可以用bitset移位后取and判断,对于乘法可以直接枚举约数

#include<bits/stdc++.h>
int _(){
    int x=0,c=getchar();
    while(c<48)c=getchar();
    while(c>47)x=x*10+c-48,c=getchar();
    return x;
}
const int N=100007,M=100100/32;
typedef unsigned int bits[M];
int n,m,B;
int t[N],a[N],id[N];
bool as[N];
bits b1,b2;
void rev(bits a,int x){a[x>>5]^=1<<(x&31);}
bool chk(bits A,bits B,int x){
    int a=x>>5,b=x&31;
    if(b){
        int c=32-b;
        for(int i=a;i<M-1;++i)if((A[i]>>b|A[i+1]<<c)&B[i-a])return 1;
    }else{
        for(int i=a;i<M;++i)if(A[i]&B[i-a])return 1;
    }
    return 0;
}
struct Q{
    int o,l,r,x,id;
    void work(){
        if(o==1){
            as[id]=chk(b1,b1,x);
        }else if(o==2){
            as[id]=chk(b2,b1,100000-x);
        }else{
            for(int i=1;i*i<=x;++i)if(x%i==0&&t[i]&&t[x/i]){
                as[id]=1;
                return;
            }
        }
    }
}qs[N];
bool operator<(Q a,Q b){
    if(id[a.l]!=id[b.l])return id[a.l]<id[b.l];
    if(a.r!=b.r)return (a.r<b.r)!=(id[a.l]&1);
    return a.id<b.id;
}
void ins(int x){
    if(!t[x]++)rev(b1,x),rev(b2,100000-x);
}
void del(int x){
    if(!--t[x])rev(b1,x),rev(b2,100000-x);
}
int main(){
    n=_();m=_();
    B=n/sqrt(m+1);
    for(int i=1;i<=n;++i)a[i]=_(),id[i]=(i-1)/B;
    for(int i=0;i<m;++i){
        qs[i].o=_();
        qs[i].l=_();
        qs[i].r=_();
        qs[i].x=_();
        qs[i].id=i;
    }
    std::sort(qs,qs+m);
    int L=1,R=0;
    for(int i=0;i<m;++i){
        int l=qs[i].l,r=qs[i].r;
        while(L>l)ins(a[--L]);
        while(R<r)ins(a[++R]);
        while(L<l)del(a[L++]);
        while(R>r)del(a[R--]);
        qs[i].work();
    }
    for(int i=0;i<n;++i)puts(as[i]?"yuno":"yumi");
    return 0;
}

 

posted on 2017-08-23 07:29  nul  阅读(167)  评论(0编辑  收藏  举报