树状数组维护+离线
最大gcd一定是某个数的一个约数,对所有询问按右端点排序,用树状数组维护即可。。
具体做法:记录每个约数出现的上一个位置pre,对于左端点落在pre之前的询问这个约数就可能是答案,所以我们对pre向前进行维护,而询问的时候从左端点往上找最大值。。。。
No Pain No Game
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 1384 Accepted Submission(s): 585
Problem Description
Life is a game,and you lose it,so you suicide.
But you can not kill yourself before you solve this problem:
Given you a sequence of number a 1, a 2, ..., a n.They are also a permutation of 1...n.
You need to answer some queries,each with the following format:
If we chose two number a,b (shouldn't be the same) from interval [l, r],what is the maximum gcd(a, b)? If there's no way to choose two distinct number(l=r) then the answer is zero.
But you can not kill yourself before you solve this problem:
Given you a sequence of number a 1, a 2, ..., a n.They are also a permutation of 1...n.
You need to answer some queries,each with the following format:
If we chose two number a,b (shouldn't be the same) from interval [l, r],what is the maximum gcd(a, b)? If there's no way to choose two distinct number(l=r) then the answer is zero.
Input
First line contains a number T(T <= 5),denote the number of test cases.
Then follow T test cases.
For each test cases,the first line contains a number n(1 <= n <= 50000).
The second line contains n number a 1, a 2, ..., a n.
The third line contains a number Q(1 <= Q <= 50000) denoting the number of queries.
Then Q lines follows,each lines contains two integer l, r(1 <= l <= r <= n),denote a query.
Then follow T test cases.
For each test cases,the first line contains a number n(1 <= n <= 50000).
The second line contains n number a 1, a 2, ..., a n.
The third line contains a number Q(1 <= Q <= 50000) denoting the number of queries.
Then Q lines follows,each lines contains two integer l, r(1 <= l <= r <= n),denote a query.
Output
For each test cases,for each query print the answer in one line.
Sample Input
1 10 8 2 4 9 5 7 10 6 1 3 5 2 10 2 4 6 9 1 4 7 10
Sample Output
5 2 2 4 3
Source
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn=60000;
vector<int> fact[maxn];
void get_factor()
{
for(int i=1;i<maxn;i++)
{
for(int j=i;j<maxn;j+=i)
{
fact[j].push_back(i);
}
}
}
int n,Q,T,tree[maxn],pre[maxn],arr[maxn],ans[maxn];
struct ASK
{
int l,r,id;
}ask[maxn];
bool cmp(ASK a,ASK b)
{
if(a.r!=b.r) return a.r<b.r;
return a.l<b.l;
}
int lowbit(int x)
{
return x&(-x);
}
void update(int p,int v) ///向下更新最大约数
{
for(int i=p;i;i-=lowbit(i)) tree[i]=max(tree[i],v);
}
int query(int p)
{
int ret=0;
for(int i=p;i<maxn;i+=lowbit(i)) ret=max(ret,tree[i]);
return ret;
}
int main()
{
scanf("%d",&T);
get_factor();
while(T--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",arr+i);
scanf("%d",&Q);
for(int i=0;i<Q;i++)
{
scanf("%d%d",&ask[i].l,&ask[i].r); ask[i].id=i;
}
sort(ask,ask+Q,cmp);
memset(tree,0,sizeof(tree));
memset(pre,-1,sizeof(pre));
int cnt=0;
for(int i=1;i<=n;i++)
{
for(int sz=fact[arr[i]].size(),j=0;j<sz;j++)
{
int fc=fact[arr[i]][j];
if(pre[fc]!=-1)
{
update(pre[fc],fc);
}
pre[fc]=i;
}
while(cnt<Q&&ask[cnt].r==i)
{
ans[ask[cnt].id]=query(ask[cnt].l);
cnt++;
}
}
for(int i=0;i<Q;i++) printf("%d\n",ans[i]);
}
return 0;
}