码迷,mamicode.com
首页 > 其他好文 > 详细

hdu 4777 Rabbit Kingdom (离线树状数组)

时间:2014-09-07 01:07:24      阅读:289      评论:0      收藏:0      [点我收藏+]

标签:os   io   ar   for   sp   on   amp   c   size   

题目大意:

给出m个查询,查询出[ l - r] 之间去 这个区间所有的数都互质的数有多少个。


思路分析:

首先我们处理出来每一个位置,左边和右边第一个与之不互质的数的位置。记在pre 和 next下。这个方法用分解质因数就好。

一个区间内的答案,等于这个区间的所有数减去有与之互质数的个数。

现在要统计的就是

1.对于一个给定的查询[l,r] 区间,统计有多少个 i (l<= i  <=r) 的pre[i] 或 next[i]在[l,r]内。

2.对于一个给定的查询[l,r]区间,统计有多个个i (l<= i < = r)的pre[i] 且 next[i]  在[l,r]内。

那么区间的答案就是  r-l+1-(统计出来的1的答案)+(统计出来的2的答案)。

对于统计2,我们就是判断有多个[pre[i],next[i] ] 在 [l,r]内。

对于统计1,我们可以用判断 [pre[i],i] 或 [i,next[i]]来替换。


#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#define lowbit(x) (x&(-x))
#define maxn 200005
#define lson num<<1,s,mid
#define rson num<<1|1,mid+1,e

using namespace std;
bool vis[200005];
int prime[50000],top_prime;

int n,m;
struct foo
{
    int s,e;
    int index,ans;
    foo(){}
    foo(int st,int ed,int id):s(st),e(ed),index(id){}
    bool operator < (const foo &cmp)const
    {
        return e<cmp.e;
    }
}Q[200005];
bool cmp_id(foo a,foo b)
{
    return a.index<b.index;
}
int bit[maxn];
void update(int pos)
{
    if(pos==0 || pos==n+1)return ;
    for(int x=pos;x<=n;x+=lowbit(x))
        bit[x]++;
}
int query(int l,int r)
{
    int ans=0;
    for(int x=r;x>=1;x-=lowbit(x))ans+=bit[x];
    for(int x=l-1;x>=1;x-=lowbit(x))ans-=bit[x];
    return ans;
}
void sieve(int n)
{
    int m=(int)sqrt(n+0.5);
    memset(vis,0,sizeof(vis));
    for(int i=2;i<=m;i++)
    {
        if(!vis[i])
        {
            for(int j=i*i;j<=n;j+=i)
                vis[j]=1;
        }
    }
    for(int i=2;i<=m;i++)
    {
        if(vis[i]==0) prime[top_prime++]=i;
    }
}
int pre[200005],next[200005],now[200005],a[200005],tnext[200005];
vector<int> p[200005];


vector <foo> ret[3];
int ans[3][maxn];
void getans(int key)
{
    memset(bit,0,sizeof bit);

    int ind=0;
    for(int i=1;i<=m;i++)
    {
        while(ind<n&&ret[key][ind].e<=Q[i].e)
        {
            update(ret[key][ind].s);
            ind++;
        }
        ans[key][Q[i].index]+=query(Q[i].s,Q[i].e);
    }
}
int num[maxn];
int main()
{
    sieve(200000);
    while(~scanf("%d%d",&n,&m))
    {
        if(!n&&!m) break;
        memset(pre,0,sizeof pre);
        memset(next,0,sizeof next);
        memset(tnext,0,sizeof tnext);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            p[a[i]].clear();
        }
        for(int i=1;i<=n;i++)
        {
            if(p[a[i]].size()) continue;
            int tmp=a[i];
            for(int j=0;prime[j]*prime[j]<=tmp&&j<top_prime;j++)
            {
                if(tmp%prime[j]==0)
                {
                    p[a[i]].push_back(prime[j]);
                    while(tmp%prime[j]==0) tmp/=prime[j];
                }
            }
            if(tmp>1) p[a[i]].push_back(tmp);
        }
        memset(now,0,sizeof(now));
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<p[a[i]].size();j++)
            {
                int tmp=p[a[i]][j];
                pre[i]=max(now[tmp],pre[i]);
                now[tmp]=i;
            }
        }
        reverse(a+1,a+1+n);
        memset(now,0,sizeof(now));
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<p[a[i]].size();j++)
            {
                int tmp=p[a[i]][j];
                tnext[i]=max(now[tmp],tnext[i]);
                now[tmp]=i;
            }
        }
        for(int i=1;i<=n;i++)
        {
            if(tnext[n-i+1]==0) next[i]=0;
            else next[i]=n-tnext[n-i+1]+1;
        }

        for(int i=1;i<=n;i++)
        {
            if(next[i]==0)next[i]=n+1;//next初始化为0
        }
        //以上为预处理出pre 和 next
        for(int i=1;i<=m;i++)
        {
            int st,ed;
            scanf("%d%d",&st,&ed);
            Q[i]=foo(st,ed,i);
            Q[i].ans=0;
            num[i]=ed-st+1;
        }
        for(int i=0;i<3;i++)ret[i].clear();

        for(int i=1;i<=n;i++)
        {
            ret[0].push_back(foo(pre[i],i,0));
            ret[1].push_back(foo(i,next[i],0));
            ret[2].push_back(foo(pre[i],next[i],0));
        }

        sort(Q+1,Q+1+m);
        for(int i=0;i<3;i++)
            sort(ret[i].begin(),ret[i].end());

        memset(ans,0,sizeof ans);
        for(int i=0;i<3;i++)
            getans(i);

        for(int i=1;i<=m;i++)
            printf("%d\n",num[i]-ans[0][i]-ans[1][i]+ans[2][i]);
    }
    return 0;
}


hdu 4777 Rabbit Kingdom (离线树状数组)

标签:os   io   ar   for   sp   on   amp   c   size   

原文地址:http://blog.csdn.net/u010709592/article/details/39108351

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!