Hungry3

梦想到达塔顶的蜗牛

hdu 4777 Rabbit Kingdom 离线树状数组

#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=200100;
struct Q
{
    int l,r,id;
    bool operator < (const Q& rhs)const
    {
        return r<rhs.r;
    }
}q[maxn];
int isp[maxn],p[maxn],w[maxn],tp[maxn];
int l[maxn],r[maxn],sum[maxn],ans[maxn];
vector<int> hav[maxn],vt[maxn];
int n,m;
void getp()
{
    int cnt,i,j;
    cnt=0;
    memset(isp,true,sizeof(isp));
    isp[0]=isp[1]=false;
    for(i=2;i<maxn;i++)
    {
        if(isp[i])
        {
            p[cnt++]=i;
            for(j=i;j<maxn;j+=i)
            isp[j]=false;
        }
    }
}
void gethav()
{
    int i,j,ti;
    for(i=2;i<maxn;i++)
    {
        ti=i;
        for(j=0;p[j]*p[j]<=ti;j++)
        {
            if(ti%p[j]==0)
            {
                hav[i].push_back(p[j]);
                while(ti%p[j]==0)ti/=p[j];
            }
        }
        if(ti>1)hav[i].push_back(ti);
    }
}
int lowbit(int i)
{
    return i&(-i);
}
void add(int pos,int key)
{
    int i,j;
    if(!pos)return;
    for(i=pos;i<=n;i+=lowbit(i))
    sum[i]+=key;
}
int getsum(int L,int R)
{
    int i,j,res;
    res=0;
    for(i=R;i>0;i-=lowbit(i))
    res+=sum[i];
    for(i=L-1;i>0;i-=lowbit(i))
    res-=sum[i];
    return res;
}
void init()
{
    int i,j,v;
    for(i=1;i<=n;i++)
    {
        scanf("%d",&w[i]);
    }
    memset(tp,-1,sizeof(tp));
    for(i=1;i<=n;i++)
    {
        l[i]=1;
        for(j=0;j<hav[w[i]].size();j++)
        {
            v=hav[w[i]][j];
            if(tp[v]!=-1)
            l[i]=max(l[i],tp[v]+1);
            tp[v]=i;
        }
    }
    memset(tp,-1,sizeof(tp));
    for(i=n;i>=1;i--)
    {
        r[i]=n;
        for(j=0;j<hav[w[i]].size();j++)
        {
            v=hav[w[i]][j];
            if(tp[v]!=-1)
            r[i]=min(r[i],tp[v]-1);
            tp[v]=i;
        }
    }
}
void slove()
{
    int i,j,ri,id;
    for(i=0;i<m;i++)
    {
        scanf("%d%d",&q[i].l,&q[i].r);
        q[i].id=i;
    }
    sort(q,q+m);
    for(i=0;i<maxn;i++)
    {
        sum[i]=0;
        vt[i].clear();
    }
    for(i=1;i<=n;i++)
    {
        vt[r[i]+1].push_back(i);
    }
    i=0;
    for(ri=1;ri<=n;ri++)
    {//加入ri点
        add(ri,1);
        add(l[ri]-1,-1);
        for(j=0;j<vt[ri].size();j++)
        {//把不能到达ri的点删掉
            id=vt[ri][j];
            add(id,-1);
            add(l[id]-1,1);
        }
        while(i<m&&q[i].r==ri)
        {//如果访问的区间刚好是ri,才去计算这个访问的答案,这样可以避免无端减少或加上影响答案的数
            //如果边处理区间边加点有麻烦,就试着换个思路,边加点边处理区间咯
            ans[q[i].id]=getsum(q[i].l,q[i].r);//以上注释该是离线处理的精髓吧=.=
            i++;
        }
    }
    for(i=0;i<m;i++)
    printf("%d\n",ans[i]);
}
int main()
{
    getp();
    gethav();
    while(scanf("%d%d",&n,&m),n||m)
    {
        init();
        slove();
    }
}
View Code

 

posted on 2013-11-12 23:58  Hungry3  阅读(170)  评论(0)    收藏  举报

导航