• Ynoi2017 由乃的玉米田


    Link
    开一个桶记录每个数字出现过多少次,同时用bitset维护(x)是否出现过。
    那么查询是否有两个数的差为(x)就是把bitset右移(x)位然后与自己,如果有位置为(1)那么就说明存在。
    查询是否有两个数的和为(x)也可以类似地做,多开一个bitset维护(10^5-x)是否出现过。
    查询是否有两个数的积为(x)可以直接枚举因数查询,注意特判(x=0)的情况。
    最后是查询是否有两个数的商为(x),首先特判(x=0)的情况,对于(xge64)的数据,我们可以暴力枚举判断。
    对于(1le x<64)的,我们把所有(x)相同询问的放一起并按左端点降序排序,用树状数组维护一下以每个点为左端点的最左右端点就好了。
    时间复杂度是(O(frac{n^2}{64}+nsqrt n+64nlog n))
    (实际上除法那里最优的分治边界应该是(sqrt{frac n{log n}}),这样复杂度就是(O(frac{n^2}{64}+nsqrt{nlog n})),不过(64)也差不多)

    #pragma GCC optimize(3)
    #include<cmath>
    #include<cstdio>
    #include<cctype>
    #include<bitset>
    #include<cstring>
    #include<algorithm>
    namespace IO
    {
        char ibuf[(1<<21)+1],*iS,*iT;
        char Get(){return (iS==iT? (iT=(iS=ibuf)+fread(ibuf,1,(1<<21)+1,stdin),(iS==iT? EOF:*iS++)):*iS++);}
        int read(){int x=0,c=Get();while(!isdigit(c))c=Get();while(isdigit(c))x=x*10+c-48,c=Get();return x;}
    }using IO::read;
    using std::sort;
    using std::bitset;
    int min(int a,int b){return a<b? a:b;}
    const int N=100007,U=100000,inf=0x3f3f3f3f;
    bitset<N>S,T;
    int n,m,bel[N],t[N],pos[N],a[N],ans[N];
    struct node{int o,l,r,x,id;}q[N],p[N];
    int operator<(const node&a,const node&b){return bel[a.l]==bel[b.l]? a.r<b.r:a.l<b.l;}
    void add(int x){if(++t[x]==1)S[x]=T[U-x]=1;}
    void del(int x){if(!--t[x])S[x]=T[U-x]=0;}
    int askmul(int x){if(!x)return S[0];for(int i=1;i*i<=x;++i)if(!(x%i)&&S[i]&&S[x/i])return 1;return 0;}
    int askdiv(int x){if(!x)return S[0]&&S.count()>1;for(int i=1,j=x;j<=U;++i,j+=x)if(S[i]&&S[j])return 1;return 0;}
    void update(int p,int v){for(;p<=n;p+=p&-p)t[p]=min(t[p],v);}
    int query(int p){int r=inf;for(;p;p^=p&-p)r=min(r,t[p]);return r;}
    int main()
    {
        n=read(),m=read();int c=0,B=sqrt(n)+rand()%5;
        for(int i=1;i<=n;++i) a[i]=read(),bel[i]=(i-1)/B+1;
        for(int i=1;i<=m;++i) q[i]={read(),read(),read(),read(),i};
        sort(q+1,q+m+1);
        for(int i=1,L=1,R=0;i<=m;++i)
        {
    	int l=q[i].l,r=q[i].r,x=q[i].x;
    	if(q[i].o==4&&q[i].x<64&&q[i].x) {p[++c]=q[i];continue;}
    	while(l<L) add(a[--L]);
    	while(R<r) add(a[++R]);
    	while(L<l) del(a[L++]);
    	while(r<R) del(a[R--]);
    	if(q[i].o==1) ans[q[i].id]=(S&S<<x).any();
    	else if(q[i].o==2) ans[q[i].id]=(S&T>>(U-x)).any();
    	else if(q[i].o==3) ans[q[i].id]=askmul(x);
    	else ans[q[i].id]=askdiv(x);
        }
        sort(p+1,p+c+1,[](const node&a,const node&b){return a.x<b.x||(a.x==b.x&&a.l>b.l);});
        for(int l=1,r;l<=c;l=r+1)
        {
    	for(r=l;p[r+1].x==p[l].x&&r<c;++r);
    	memset(t,0x3f,sizeof t),memset(pos,0x3f,sizeof pos);
    	for(int i=l,j=n;i<=r;++i)
            {
                for(;j>=p[i].l;--j)
                {
    		pos[a[j]]=j;
    		if(1ll*a[j]*p[l].x<=U) update(j,pos[a[j]*p[l].x]);
    		if(!(a[j]%p[l].x)) update(j,pos[a[j]/p[l].x]);
                }
    	    ans[p[i].id]=p[i].l>p[i].r? 0:query(p[i].r)<=p[i].r;
            }
        }
        for(int i=1;i<=m;++i) puts(ans[i]? "yuno":"yumi");
    }
    
  • 相关阅读:
    nsmutableset
    数组建立 不可变数组 排序 遍历
    字符串截取 拼接 转换 长度 查询 比较
    字典排序
    数字字典结合
    可变字典
    字典
    可变字符串
    oc block排序
    oc中文首字母排序
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12217302.html
Copyright © 2020-2023  润新知