HDU 4777 Rabbit Kingdom

杭州区域赛的题目


题意:

给定区间[l,r] ,求[l,r]内有多少个数满足与区间内其他数都互质。


思路:

处理出每个数,最左边能互质到的位置L[i],以及右边R[i]。(具体方法看代码)

然后用树状数组维护区间的覆盖,按l离线查询。

然后从左往右扫。对于当前位置p,找出所有L[i]==p的数。然后i位置+1,R[i]+1的位置-1。因为p以及p以后的位置,这个L[i]都能覆盖到。

离开位置p的时候,要把p位置这个数的覆盖去掉。即p位置-1,R[p]+1的位置+1。

如果p位置上有查询,那么sum(r)就是答案。

总复杂度O(nlogn)


这份代码C++能AC,G++MEL。。。其实C++也要32760KB,因为用了很多vector,加上数据有20W,vector实际比存储的要大。虽然理论计算是不会MLE的。

code:

#include <algorithm>
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <math.h>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <list>
#include <set>
#include <map>
using namespace std;
    
#define N  200010
#define ll long long
#define ALL(x)     x.begin(),x.end()
#define CLR(x,a) memset(x,a,sizeof(x))
typedef pair<int,int> PI;
const int INF=0x3fffffff;
const int MOD   =1000000007;
const double EPS=1e-7;

class BIT{
private:
    int sum[N],n;    
public:
    void init(int n){
        this->n=n;
        fill(sum+1,sum+n+1,0);
    }

    void add(int i,int x){
        for(;i<=n;i+=-i&i) sum[i]+=x;
    }

    int get(int i){
        int ans=0;
        for(;i>=1;i-=-i&i) ans+=sum[i];
        return ans;
    }

}T;

vector<PI > Q[N];
vector<int> pos[N],prm[N];
int ans[N],l[N],r[N],idx[N],a[N];

void solve(int n,int d[]){
    CLR(idx,0);
    for(int i=1;i<=n;i++){
        d[i]=0;
        for(int j=0;j<prm[a[i]].size();j++){
            d[i]=max(d[i],idx[prm[a[i]][j]]);
            idx[prm[a[i]][j]]=i;
        }
        d[i]++;
    }
}

void pretreat(int n){
    solve(n,l);
    reverse(a+1,a+n+1);
    solve(n,r);
    reverse(a+1,a+n+1);
    for(int i=1,j=n;i<j;i++,j--) swap(r[i],r[j]);
    for(int i=1;i<=n;i++) r[i]=n-r[i]+2;
    for(int i=1;i<=n;i++) pos[l[i]].push_back(i);
}

bool vis[N];

int main(){
    int n,m;
    for(int i=2;i<N;i++) if(!vis[i]){
        for(ll j=1ll*i*i;j<N;j+=i) vis[i]=true;
        for(int j=i;j<N;j+=i) prm[j].push_back(i);
    }
    while(~scanf("%d%d",&n,&m),n||m){
        for(int i=1;i<=n;i++){
            scanf("%d",a+i);
            pos[i].clear(), Q[i].clear();
        }
        for(int i=0;i<m;i++){
            int l,r;
            scanf("%d%d",&l,&r);
            Q[l].push_back(make_pair(r,i));
        }
        pretreat(n);
        T.init(n+1);
        for(int i=1;i<=n;i++){
            for(int j=0;j<pos[i].size();j++){
                int p=pos[i][j];
                T.add(p,1);
                T.add(r[p],-1);
            }
            for(int j=0;j<Q[i].size();j++) 
                ans[Q[i][j].second]=T.get(Q[i][j].first);
            T.add(i,-1);
            T.add(r[i],1);
        }
        for(int i=0;i<m;i++) printf("%d\n",ans[i]);
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值