题目: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;
}