HDU 4777 Rabbit Kingdom 解题报告

来源:互联网 发布:iphone软件授权 编辑:程序博客网 时间:2024/06/05 19:00

题目

题意:

有n个数字,m个查询,每次询问[l,r]这些数字中,和其他数都互质的数有多少个。

题解:

从左到右遍历,对每个数因子分解,如果它含有的因子在之前也有数含有,那么便可知那个数和它不互质,所以可以求出每个数i左边第一个和它不互质的数的位置,记为lefi,右边同理,记为rigi。

然后将查询按l排序,从左往右遍历原数组,遍历到j时,若存在i使得j-1=lefi,则可知从j到(rigi)-1都和i互质,因此如果有查询的l=j,而r=[i,rigi)的话,这个区间里i是一个满足要求的数。这里可以用线段树或者树状数组。

代码:

//Time:1843ms//Memory:9216KB//Length:2574B#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define MP(x,y) make_pair(x,y)#define FI first#define SE secondconst int MAXN = 200010;int tree[MAXN];int pri[MAXN],ptop,yin[MAXN];int arr[MAXN],pre[MAXN],ans[MAXN],bel[MAXN];pair<int,int> pa[MAXN];bool vi[MAXN];struct _query{    int l,r,id;    bool operator < (const _query &b)   const    {        return l<b.l;    }}que[MAXN];void cal(int n){    memset(yin,-1,sizeof(yin));    for(int i=0;i<n;++i)    {        int pos=-1,tmp=arr[i];        for(int j=0;(long long)pri[j]*pri[j]<=tmp;++j)            if(tmp%pri[j]==0)            {                pos=max(pos,yin[j]);                yin[j]=i;                while(tmp%pri[j]==0)    tmp/=pri[j];            }        if(tmp>1)        {            pos=max(pos,yin[bel[tmp]]);            yin[bel[tmp]]=i;        }        pre[i]=pos+1;    }}void add(int h,int num){    ++h;    while(h<MAXN)    {        tree[h]+=num;        h+=h&(-h);    }}int query(int h){    ++h;    int cnt=0;    while(h)    {        cnt+=tree[h];        h-=h&(-h);    }    return cnt;}int main(){    //freopen("/home/moor/Code/input","r",stdin);    int n,m,ql,pl;    ptop=0;    memset(vi,0,sizeof(vi));    for(int i=2;i<MAXN;++i)        if(!vi[i])        {            bel[i]=ptop;            pri[ptop++]=i;            for(int j=i;j<MAXN;j+=i)    vi[j]=1;        }    while(scanf("%d%d",&n,&m)==2&&n)    {        for(int i=0;i<n;++i)    scanf("%d",&arr[i]);        cal(n);        for(int i=0;i<n;++i)    pa[i]=MP(pre[i],i);        sort(pa,pa+n);        for(int i=0,j=n-1;i<j;++i,--j)  swap(arr[i],arr[j]);        cal(n);        for(int i=0;i<n;++i)    pre[i]=n-1-pre[i];        for(int i=0,j=n-1;i<j;++i,--j)  swap(arr[i],arr[j]),swap(pre[i],pre[j]);        for(int i=0;i<m;++i)            scanf("%d%d",&que[i].l,&que[i].r),que[i].id=i,--que[i].l,--que[i].r;        sort(que,que+m);        ql=0,pl=0;        memset(tree,0,sizeof(tree));        for(int i=0;i<n;++i)        {            if(i)            {                add(pre[i-1]+1,1);                add(i-1,-1);            }            while(pl<n&&pa[pl].FI==i)            {                add(pa[pl].SE,1);                add(pre[pa[pl].SE]+1,-1);                ++pl;            }            while(ql<m&&que[ql].l==i)            {                ans[que[ql].id]=query(que[ql].r);                ++ql;            }        }        for(int i=0;i<m;++i)    printf("%d\n",ans[i]);    }    return 0;}


原创粉丝点击