题目链接:HDU-4630
题意:1~n的全排列,多次询问区间内,两个数字gcd的最大值
预处理出一个数字的所有因子,如果一个因子出现两次以上说明可能作为答案。
对询问按照右端点排序。
按位置从小到大枚举,枚举该数字的所有因子,如果之前该因子出现过,则在该因子之前的位置处更新值为该因子。
如果要用线段树维护,那直接做就行。
如果要用树状数组维护,树状数组维护的是具有前缀性质的, [ l , r ] [l,r] [l,r]的最大值显然不能由 [ 1 , l − 1 ] [1,l-1] [1,l−1]与 [ 1 , r ] [1,r] [1,r]得到,那这里用一个比较优秀的想法,因为我们对询问排序了,那按照位置更新,一定到查询的时候,更新过的位置都是<=当前位置的,那么我们可以将树状数组弄成后缀的形式,即可处理区间最值查询问题。一般情况下例如维护区间和,如果将一个位置加的话,是会对其之后的位置造成影响,这里是之前。
线段树
#include
using namespace std;
const int maxn=5e4+7;
vector<int> v[maxn];
int maxx[maxn<<2|1];
void pushup(int k){
maxx[k]=max(maxx[k<<1],maxx[k<<1|1]);
}
void build(int l,int r,int k){
maxx[k]=0;
if(l==r) return ;
int mid=(l+r)>>1;
build(l,mid,k<<1);
build(mid+1,r,k<<1|1);
}
void updata(int l,int r,int k,int id,int val){
if(l==r){
maxx[k]=max(maxx[k],val);
return ;
}
int mid=(l+r)>>1;
if(id<=mid) updata(l,mid,k<<1,id,val);
else updata(mid+1,r,k<<1|1,id,val);
pushup(k);
}
int myfind(int l,int r,int k,int L,int R){
if(l>=L&&r<=R) return maxx[k];
int mid=(l+r)>>1;
int res=0;
if(L<=mid) res=max(res,myfind(l,mid,k<<1,L,R));
if(R>mid) res=max(res,myfind(mid+1,r,k<<1|1,L,R));
return res;
}
struct Node{
int l,r,id;
bool operator <(const Node& x)const{
return r<x.r;
}
}a[maxn];
int b[maxn];
int res[maxn];
int pos[maxn];
int main(){
for(int i=1;i<=50000;++i)
for(int j=i;j<=50000;j+=i) v[j].push_back(i);
int t,n,q,x,y,val;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
build(1,n,1);
for(int i=1;i<=n;++i){
scanf("%d",&b[i]);
//pos[x]=i;
}
scanf("%d",&q);
for(int i=1;i<=q;++i){
scanf("%d%d",&a[i].l,&a[i].r);
a[i].id=i;
}
sort(a+1,a+1+q);
for(int i=1,j=1;i<=n;++i){
for(int k=0;k<v[b[i]].size();++k){
if(pos[v[b[i]][k]]){
//cout<
updata(1,n,1,pos[v[b[i]][k]],v[b[i]][k]);
}
pos[v[b[i]][k]]=i;
}
while(j<=q&&a[j].r==i){
if(a[j].l==a[j].r) res[a[j].id]=0;
else res[a[j].id]=myfind(1,n,1,a[j].l,a[j].r);
++j;
}
}
for(int i=1;i<=q;++i){
printf("%d\n",res[i]);
res[i]=0;
}
for(int i=1;i<=n;++i) pos[i]=0;
}
return 0;
}
树状数组
#include
using namespace std;
const int maxn=5e4+7;
vector<int> v[maxn];
int maxx[maxn];
void add(int x,int v){
for(;x;x-=x&-x) maxx[x]=max(maxx[x],v);
}
int n;
int ask(int x){
int res=0;
for(;x<=n;x+=x&-x) res=max(res,maxx[x]);
return res;
}
struct Node{
int l,r,id;
bool operator <(const Node& x)const{
return r<x.r;
}
}a[maxn];
int b[maxn];
int res[maxn];
int pos[maxn];
int main(){
for(int i=1;i<=50000;++i)
for(int j=i;j<=50000;j+=i) v[j].push_back(i);
int t,q,x,y,val;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=1;i<=n;++i){
scanf("%d",&b[i]);
maxx[i]=0;
}
scanf("%d",&q);
for(int i=1;i<=q;++i){
scanf("%d%d",&a[i].l,&a[i].r);
a[i].id=i;
}
sort(a+1,a+1+q);
for(int i=1,j=1;i<=n;++i){
for(int k=0;k<v[b[i]].size();++k){
if(pos[v[b[i]][k]]){
add(pos[v[b[i]][k]],v[b[i]][k]);
}
pos[v[b[i]][k]]=i;
}
while(j<=q&&a[j].r==i){
if(a[j].l==a[j].r) res[a[j].id]=0;
else res[a[j].id]=ask(a[j].l);
++j;
}
}
for(int i=1;i<=q;++i){
printf("%d\n",res[i]);
res[i]=0;
}
for(int i=1;i<=n;++i) pos[i]=0;
}
return 0;
}