借鉴这里:http://blog.youkuaiyun.com/dongdongzhang_/article/details/9670039
有N个数, 是 1~N的一个排列。有M个询问, 每次询问一个区间, 问从这个区间中,取两个数的最大的最大公约数。
首先要求出每个数对应的因子存起来。在一个区间内, 如果一个因子出现两次,该因子就肯定是该区间的一个解。 而出现两次并且是最大。 就是该区间的最优解。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<map>
#include<algorithm>
using namespace std;
#define clr(x) memset(x,0,sizeof(x))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define havemid int m=(l+r)>>1
#define left (rt<<1)
#define right (rt<<1|1)
const int maxn=50005;
int sum[maxn<<2];
int a[50005];
void pushup(int rt){
sum[rt]=max(sum[left],sum[right]);
}
void build(int l,int r,int rt){
if(l==r){
sum[rt]=0;
return ;
}
havemid;
build(lson);
build(rson);
pushup(rt);
}
void update(int p,int add,int l,int r,int rt){
if(l==r){
sum[rt]=max(sum[rt],add);return ;
}
havemid;
if(p<=m)update(p,add,lson);
else update(p,add,rson);
pushup(rt);
}
int query(int L,int R,int l,int r,int rt){
if(L<=l&&r<=R)return sum[rt];
havemid;
int ret=0;
if(L<=m)ret=query(L,R,lson);
if(R>m)ret=max(ret,query(L,R,rson));
return ret;
}
struct node {
int x,y,id;
}Q[50010];
int cmp(struct node a,struct node b){
return a.y<b.y;
}
int mp[50010];
int temp[50010][100];
int top[50010];
int res[50010];
int main(){
int T,n,m,i,j;
scanf("%d",&T);
while(T--){
clr(mp);
clr(top);
clr(temp);
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%d",&a[i]);
for(j=1;j*j<=a[i];j++){
if(a[i]%j==0){
temp[i][top[i]++]=a[i]/j;
if(j*j!=a[i])temp[i][top[i]++]=j;
}
}
}
build(1,n,1);
scanf("%d",&m);
for(i=0;i<m;i++){
scanf("%d%d",&Q[i].x,&Q[i].y);
Q[i].id=i;
}
sort(Q,Q+m,cmp);
int k=0;
for(i=1;i<=n;i++){
if(k>=m)break;
for(j=0;j<top[i];j++){
int t=temp[i][j];
if(mp[t]!=0){
update(mp[t],t,1,n,1);
}
mp[t]=i;
}
while(i==Q[k].y){
res[Q[k].id]=query(Q[k].x,Q[k].y,1,n,1);
k++;
}
}
for(i=0;i<m;i++){
printf("%d\n",res[i]);
}
}
return 0;
}