Maximum number, GCD condition (CodeChef)

题目:http://www.codechef.com/problems/ANUGCD/


给一个数组,m个查询,查询格式G X Y,查询[X,Y]区间中的数与G的GCD>1,且要最大的,外加这个数的次数。

想法:对每个素数建一个线段树,一开始做的时候,只建了sqrt(10W)的线段树,其他大的素数,就暴力,结果TLE,后来就干脆对每个<10W的素数建树,静态数组开不下,开的动态的。

#include <stdio.h>
#include <string.h>
#include <map>
#include <vector>
#include <ctime>
#include <math.h>
#include <algorithm>
using namespace std;

inline int input(){
    int ret=0;
    char c=getchar();
    while(c<'0'||c>'9') c=getchar();
    while(c>='0'&&c<='9'){
        ret=ret*10+c-'0';
        c=getchar();
    }
    return ret;
}
inline void output(int x){
    if(x<0){
        putchar('-');
        x=-x;
    }
    int len=0,data[10];
    while(x){
        data[len++]=x%10;
        x/=10;
    }
    if(!len)
        data[len++]=0;
    while(len--)
        putchar(data[len]+48);
}

#define N 100005
#define L t<<1
#define R t<<1|1
typedef pair<int,int> ii;
int a[N],n,m,g,x,y;
vector<int>pp[N];
bool pri[N];
int p[N/10];
int pos[N];
int cnt=0;

inline void init(){
    memset(pri,0,sizeof(pri));
    pri[0]=pri[1]=1;
    for(int i=2;i<=100000;i++){
        if(!pri[i]){
            pos[i]=cnt;
            p[cnt++]=i;
            for(int j=i*2;j<=100000;j+=i) pri[j]=1;
        }
    }
}
struct node{
    node* l;
    node* r;
    int x,y;
    ii val;
};
inline void push_up(node *t){
    if(t->l->val.first > t->r->val.first){
        t->val = t->l->val;
    }
    else if(t->l->val.first < t->r->val.first){
        t->val = t->r->val;
    }
    else{
        t->val = t->l->val;
        t->val.second += t->r->val.second;
    }
}
inline void build(node *t,int l,int r,int id){
    t->x = l;
    t->y = r;
    if(l == r){
        t->val=make_pair(a[pp[id][l-1]],1);
    }
    else{
        int mid=(l+r)>>1;
        t->l = new node();
        t->r = new node();
        build(t->l,l,mid,id);
        build(t->r,mid+1,r,id);
        push_up(t);
    }
}
inline ii query(node *t,int l,int r){
    int x = t->x , y = t->y;
    if(x>=l && y<=r){
        return t->val;
    }
    if(x>r || y<l){
        return make_pair(-1,0);
    }
    int mid=(x+y)>>1;
    if(r<=mid) return query(t->l,l,r);
    else if(l>mid) return query(t->r,l,r);
    else{
        ii a=query(t->l,l,mid);
        ii b=query(t->r,mid+1,r);
        if(a.first > b.first) return a;
        else if(a.first < b.first) return b;
        else{
            a.second += b.second;
            return a;
        }
    }
}

inline int search(int id,int x){
    int s=0,t=pp[id].size()-1;
    while(s<=t){
        int mid=(s+t)>>1;
        int val=pp[id][mid];
        if(val == x) return mid;
        if(val <x )s=mid+1;
        else t=mid-1;
    }
    return s;
}
int main(){
    init();
    node *root[cnt+1];
    for(int i=0;i<=cnt;i++){
        root[i] = new node();
    }
    n=input(),m=input();
    for(int i=1;i<=n;i++){
        a[i]=input();
        int w=a[i];
        for(int j=0;j<cnt;j++){
            if(pri[w] == 0){
                pp[pos[w]].push_back(i);
                w=1;
                break;
            }
            if(w%p[j] == 0){
                pp[j].push_back(i);
                while(w>1 && w%p[j]==0) w/=p[j];
                if(w<=1) break;
            }
        }
    }
    for(int i=0;i<cnt;i++){
        int S=pp[i].size();
        if(S==0) continue;
        build(root[i],1,S,i);
    }
    while(m--){
        g=input(),x=input(),y=input();
        ii ans=make_pair(-1,-1);
        for(int i=0;i<cnt;i++){
            if(pri[g] == 0){
                int ind=pos[g];
                int l=search(ind,x)+1;
                int r=search(ind,y);
                if(r>=pp[ind].size()) r=pp[ind].size();
                else{
                    if(pp[ind][r]>y) r--;
                    r+=1;
                }
                if(r>=l){
                    ii tmp=query(root[ind],l,r);
                    if(tmp.first > ans.first){
                        ans=tmp;
                    }
                }
                g=1;
                break;
            }
            if(g%p[i]==0){
                int l=search(i,x)+1;
                int r=search(i,y);
                if(r>=pp[i].size()) r=pp[i].size();
                else{
                    if(pp[i][r]>y) r--;
                    r+=1;
                }
                if(r>=l){
                    ii tmp=query(root[i],l,r);
                    if(tmp.first > ans.first){
                        ans=tmp;
                    }
                }
                while(g>1 && g%p[i]==0) g/=p[i];
                if(g<=1) break;
            }
        }
        if(ans.first<=0 || ans.second<=0) puts("-1 -1");
        else{
            output(ans.first),putchar(' ');
            output(ans.second),putchar('\n');
        }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值