zoukankan      html  css  js  c++  java
  • 题解 P5629 【【AFOI-19】区间与除法】

    这题我们可以想到将每个数字变成 (d) 进制的数,消灭数可以看成是 (d) 进制下原数是这个数 (d) 进制下的一段前缀。

    于是可以使用 (Trie) 来实现这个过程,于是可以先将这 (m) 个原数 insert,然后再去查询。

    一个数有多个前缀,我们可以选择其中最短的一个,因为这样是最优秀的,可以理解为越短的串延伸出来的串就越多,而越长的串则通用性就越差。

    于是我们就可以求出是每个数会选择哪个原数进行消灭,我们可以将状态存在一个 long long 里面,需要做到的就是区间或。

    无修改,只有区间或,可以想到使用倍增(ST表)来求,因为或有着跟 (min)(max) 一样好的性质。

    code(目前的最优解):

    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define LL long long
    #define pb push_back
    #define mp make_pair
    #define SZ(x) ((int)x.size()-1)
    #define ms(a,b) memset(a,b,sizeof a)
    #define F(i,a,b) for(int i=(a);i<=(b);++i)
    #define DF(i,a,b) for(int i=(a);i>=(b);--i)
    #define debug(b,a) cerr<<"D:";F(i,1,b-1)cerr<<"   ";cerr<<" "<<#a<<" => "<<(a)<<"  <="<<__LINE__<<"L"<<endl
    using namespace std;
    inline LL read(){char ch=getchar(); LL w=1,c=0;
    	for(;!isdigit(ch);ch=getchar()) if (ch=='-') w=-1;
    	for(;isdigit(ch);ch=getchar()) c=(c<<1)+(c<<3)+(ch^48);
    	return w*c;
    }
    const int N=5e5+10,M=65;
    int cnt,n,m,d,q,pos[15][M*65],tot,vis[M*25],lg2[N],tmp[N];
    LL a[N],b[M];
    LL f[25][N];
    void insert(LL x,int y){
    	int tot=0;
    	for(;x;x/=d)tmp[++tot]=x%d;
    	int num=0;
    	DF(i,tot,1){
    		if(vis[num])return;
    		if(!pos[tmp[i]][num])pos[tmp[i]][num]=++cnt;
    		num=pos[tmp[i]][num];
    	}vis[num]=y;
    }
    int query(LL x){
    	int tot=0;
    	for(;x;x/=d)tmp[++tot]=x%d;
    	int num=0;
    	DF(i,tot,1){
    		if(vis[num])return vis[num];
    		if(!pos[tmp[i]][num])return -1;
    		num=pos[tmp[i]][num];
    	}return vis[num]?vis[num]:-1;
    }
    signed main(){
    	n=read(),m=read(),d=read(),q=read();
    	F(i,2,n)lg2[i]=lg2[i>>1]+1;
    	F(i,1,n)a[i]=read();
    	F(i,1,m)b[i]=read();
    	sort(b+1,b+m+1);
    	F(i,1,m)
    		insert(b[i],i);
    	F(i,1,n){
    		int c=query(a[i]);
    		if(~c)f[0][i]=(1ll<<c);
    	}
    	F(i,1,lg2[n])
    		F(j,1,n)
    			f[i][j]=f[i-1][j]|f[i-1][j+(1<<(i-1))];
    	while(q--){
    		int l=read(),r=read(),ans=0;
    		int dist=(r-l+1);
    		LL z=f[lg2[dist]][l]|f[lg2[dist]][r-(1<<lg2[dist])+1];
    		for(;z;z&=(z-1))ans++;
    		printf("%d
    ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    Spring(3)
    Spring(2)
    Spring(1)
    2016年给自己的一个清单计划
    今天早上是我第一次发博客,请大家多多关照
    QTP知识积累
    [转]基于实际测试的功能测试点总结
    Django之模板
    Django之视图
    HTML
  • 原文地址:https://www.cnblogs.com/zhaohaikun/p/14790447.html
Copyright © 2011-2022 走看看