hdu 4777 Rabbit Kingdom

题意:给N个数,有M个查询,问区间[L,R]之间有多少个数与这个区间内的其他数都互质。

易得,一个区间内的数的个数减去,与其他数不互质的数即可——即离当前数i左边最近的不互质的数的位置(设为L[i])和右边最近的不互质的数的位置(设为R[i])有一个在区间[L,R]内。那么问题就变成统计:1.区间[L,R]中有多少个数的L[i]或R[i]在区间[L,R]内。2.多少个数的L[i]且R[i]在区间[L,R]内。对于每个询问,答案就是区间内的数减去1的结果,再加上2的结果。

2的结果其实就是询问有多少个区间[L[i],R[i]]完全在给定区间[L,R]内。其实1也可以转化为相同的问题,即区间[L[i],i]或[R[i],i],是否在给定区间内。

对于问有多少个区间是在给定的区间内,可以直接离线搞。

#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <algorithm>
#include <stdlib.h>
#include <string>
#include <queue>
#include <map>
#include <vector>
#include <set>
#define maxn 1000010
#define oo 1000000000
#define clearAll(a) memset(a,0,sizeof(a))
#define sq(a) ((a)*(a))

#define LL(x) (x<<1)
#define RR(x) (x<<1|1)
#define MID(a,b) (a+((b-a)>>1))

using namespace std;

typedef long long ll;

const int N=200015;

struct Range
{
    int st,ed,ind;
    Range(){}
    Range(int st,int ed,int ind) :
        st(st),ed(ed),ind(ind) {}
    bool operator<(const Range &B)const
    {
        return ed<B.ed;
    }
};

int n,m,mx;
int A[N],L[N],R[N],pos[N];
int ans[3][N],num[N];

vector<Range>rab[3],range;

void fun(bool flag)
{
    if(flag==0)
    {
        for(int i=0;i<=mx;i++) pos[i]=0;

        for(int i=1;i<=n;i++)
        {
            int tmp=A[i];
            for(int j=2;j*j<=tmp;j++)
            {
                if(tmp%j) continue;
                L[i]=max(L[i],pos[j]);
                pos[j]=i;
                while(tmp%j==0) tmp/=j;
            }
            if(tmp!=1)
            {
                L[i]=max(L[i],pos[tmp]);
                pos[tmp]=i;
            }
        }
    }
    else
    {
        for(int i=0;i<=mx;i++) pos[i]=n+1;

        for(int i=n;i>=1;i--)
        {
            int tmp=A[i];
            for(int j=2;j*j<=tmp;j++)
            {
                if(tmp%j) continue;
                R[i]=min(R[i],pos[j]);
                pos[j]=i;
                while(tmp%j==0) tmp/=j;
            }
            if(tmp!=1)
            {
                R[i]=min(R[i],pos[tmp]);
                pos[tmp]=i;
            }
        }
    }
}


struct BIT
{
    int T[N];

    void clear() { for(int i=1;i<=n+10;i++) T[i]=0; }

    int lowbit(int x) { return x&(-x); }
    void updata(int pos)
    {
        if(pos==0||pos==n+1) return;
        for(int i=pos;i<=n;i+=lowbit(i)) T[i]++;
    }
    int query(int st,int ed)
    {
        int ans=0;
        for(int i=ed;i>=1;i-=lowbit(i)) ans+=T[i];
        for(int i=st-1;i>=1;i-=lowbit(i)) ans-=T[i];
        return ans;
    }
}seg;

void getAns(int key)
{
    seg.clear();

    int ind=0;
    for(int i=0;i<m;i++)
    {
        int st=range[i].st;
        int ed=range[i].ed;
        int id=range[i].ind;

        while(ind<n&&rab[key][ind].ed<=ed)
        {
            seg.updata(rab[key][ind].st);
            ind++;
        }
        ans[key][id]+=seg.query(st,ed);
    }
}

int main()
{

    while(scanf("%d%d",&n,&m)!=EOF)
    {
        if(n==0&&m==0) break;

        range.clear(); mx=0;
        rab[0].clear(); rab[1].clear(); rab[2].clear();

        for(int i=0;i<N;i++)
        {
            L[i]=0; R[i]=n+1;
            ans[0][i]=ans[1][i]=ans[2][i]=0;
        }

        for(int i=1;i<=n;i++)
        {
            scanf("%d",&A[i]);
            mx=max(mx,A[i]);
        }
        for(int i=0;i<m;i++)
        {
            int x,y; scanf("%d%d",&x,&y);
            num[i]=y-x+1;
            range.push_back(Range(x,y,i));
        }

        fun(0); fun(1);

        for(int i=1;i<=n;i++)
        {
            rab[0].push_back(Range(L[i],i,0));
            rab[1].push_back(Range(i,R[i],0));
            rab[2].push_back(Range(L[i],R[i],0));
        }

        sort(range.begin(),range.end());
        sort(rab[0].begin(),rab[0].end());
        sort(rab[1].begin(),rab[1].end());
        sort(rab[2].begin(),rab[2].end());

        getAns(0);
        getAns(1);
        getAns(2);

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



阅读更多
个人分类: 线段树及数据结构
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭