题目链接: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<bits/stdc++.h>
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,</