hdu 4777 2013ACM/ICPC杭州现场赛 H题 Rabbit Kingdom

杭州未能取得奖项真是千古恨啊。赛后和学长讨论了H题。写了下。

思路:对于每个数求出它能互质的前范围和后范围。然后用树状数组离线处理询问。对于每个询问,其结果是 前范围和后范围包含询问区间的个数减去前范围到下标-1包含询问区间的个数减去下标+1到后范围包含询问区间的个数。

由于没地交,我也不知道能不能AC。。。。。。(hdu已ac

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int p[200010];
struct node
{
    int l,z,r;
}t[200010];
struct query
{
    int l,r,num;
}q[200010];
int c[200010],s1[200010],s2[200010],s3[200010];
int m,n,a[200010],d[200010];
void prime()
{
    memset(p,0,sizeof(p));
    p[1]=1;
    for(int i=2;i<=200000;i++)
    {
        if(p[i]==0)
        {
            for(int j=i;j<=200000;j+=i)p[j]=i;
        }
    }
}
bool cmpq(query x,query y)
{
    return x.l<y.l;
}
bool cmp1(node x,node y)
{
    return x.l<y.l;
}
bool cmp2(node x,node y)
{
    return x.z<y.z;
}
int lowbit(int x)
{
    return x&(-x);
}
void add(int w,int v)
{
    for(int i=w;i<=n;i+=lowbit(i))
    {
        c[i]+=v;
    }
}
int sum(int w)
{
    int s=0;
    for(int i=w;i>=1;i-=lowbit(i))
    {
        s+=c[i];
    }
    return s;
}
int main()
{
    prime();
    while(scanf("%d%d",&n,&m))
    {
        if(m==0&&n==0)break;
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&q[i].l,&q[i].r);
            q[i].num=i;
        }
        memset(d,0,sizeof(d));
        for(int i=1;i<=n;i++)
        {
            int mm=1;
            t[i].z=i;
            for(int j=a[i];j!=1;j=j/p[j])
            {
                if(d[p[j]]+1>mm&&d[p[j]]!=i)
                {
                    mm=d[p[j]]+1;
                }
                d[p[j]]=i;
            }
            t[i].l=mm;
        }
        for(int i=0;i<=200000;i++)d[i]=n+1;
        for(int i=n;i>=1;i--)
        {
            int mm=n;
            for(int j=a[i];j!=1;j=j/p[j])
            {
                if(d[p[j]]-1<mm&&d[p[j]]!=i)
                {
                    mm=d[p[j]]-1;
                }
                d[p[j]]=i;
            }
            t[i].r=mm;
        }
        sort(q+1,q+m+1,cmpq);
        memset(c,0,sizeof(c));
        sort(t+1,t+n+1,cmp1);
        int w=1;
        for(int i=1;i<=m;i++)
        {
            for(;w<=n;w++)
            {
                if(t[w].l>q[i].l)break;
                add(t[w].l,1);
                add(t[w].r+1,-1);
            }
            s1[q[i].num]=sum(q[i].r);
        }
        memset(c,0,sizeof(c));
        w=1;
        for(int i=1;i<=m;i++)
        {
            for(;w<=n;w++)
            {
                if(t[w].l>q[i].l)break;
                add(t[w].l,1);
                add(t[w].z,-1);
            }
            s2[q[i].num]=sum(q[i].r);
        }
        memset(c,0,sizeof(c));
        sort(t+1,t+n+1,cmp2);
        w=1;
        for(int i=1;i<=m;i++)
        {
            for(;w<=n;w++)
            {
                if(t[w].z>=q[i].l)break;
                add(t[w].z,1);
                add(t[w].r+1,-1);
            }
            s3[q[i].num]=sum(q[i].r);
        }
        for(int i=1;i<=m;i++)
        {
            printf("%d\n",s1[i]-s2[i]-s3[i]);
        }
    }
    return 0;
}


你可能感兴趣的:(树状数组,Baoge)