hdu 4630
算是一道好题目吧,不断地求一段区间的最大公约数,‘|’表示有x这个约数,‘o’表示没有,
|ooo|oo|那么我们可以根据最后一个‘|’的位置来进行在线查询,将要查询的区间按右边界进行排序,更新‘|’的前一个位置。用线段树。。。。。。
//hdu 4630 线段树
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <string>
#include <cstring>
#include <stdio.h>
#include <bitset>
#include <queue>
#define maxn 50002
using namespace std;
int num[maxn],pos[maxn],n,m,p[maxn];
vector<int> g[maxn+5];
struct e1
{
int x,y,id,ans;
}que[maxn];
struct e2
{
int l,r,ma;
}tree[maxn*6];
bool cmp(e1 a,e1 b)
{
if(a.y==b.y)
return a.x<b.x;
return a.y<b.y;
}
void pushup(int a)
{
tree[a].ma=max(tree[a*2+1].ma,tree[a*2].ma);
}
void build(int a,int l,int r)
{
tree[a].l=l;
tree[a].r=r;
tree[a].ma=0;
if(l==r)
return;
int mid=(l+r)/2;
build(a*2,l,mid);
build(a*2+1,mid+1,r);
}
void insert(int a,int p,int v)
{
if(tree[a].l==tree[a].r)
{
tree[a].ma=max(tree[a].ma,v);
return;
}
int mid=(tree[a].l+tree[a].r)/2;
if(p<=mid)
insert(a*2,p,v);
else
insert(a*2+1,p,v);
pushup(a);
}
int query(int a,int l,int r)
{
if(l<=tree[a].l&&tree[a].r<=r)
return tree[a].ma;
int mid=(tree[a].l+tree[a].r)/2;
int ans=0;
if(l<=mid)
ans=max(query(a*2,l,r),ans);
if(mid<r)
ans=max(query(a*2+1,l,r),ans);
return ans;
}
int main()
{
int T,j,k;
for(j=1;j<=maxn;j++)
for(k=j;k<=maxn;k+=j)
g[k].push_back(j);
//freopen("d:\\in.txt","r",stdin);
scanf("%d",&T);
while(T--)
{
int i,ii,cnt=0;
memset(pos,0,sizeof(pos));
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%d",&num[i]);
scanf("%d",&m);
for(i=0;i<m;i++)
{
scanf("%d %d",&que[i].x,&que[i].y);
que[i].id=i;
}
sort(que,que+m,cmp);
build(1,0,n);
for(i=1;i<=n;i++)
{
int u=num[i];
for(ii=0;ii<g[u].size();ii++)
{
insert(1,pos[g[u][ii]],g[u][ii]);
pos[g[u][ii]]=i;
}
while(cnt<m&&que[cnt].y==i)
{
p[que[cnt].id]=query(1,que[cnt].x,que[cnt].y);
cnt++;
}
}
for(i=0;i<m;i++)
printf("%d\n",p[i]);
}
return 0;
}