题意:一个区间,m次询问(l,r),求a[l]%a[l+1]%...%a[r]
题解:比赛时候,想到的是二分线段树,说了以后,学弟说可能会退化,当时没多想,其实仔细想想,构造不出来那样的数据吧,线段树常数比较大,看到队友用RMQ,常数小
其实本质差不多,就是先找前一半的最小,看看是不是小于a[l],如果是,就继续在左找,没有就在右找,如果右也没有,就退
int a[100010],n;
int d[100010][30];
void RMQ_init(){
for(int i=0;i<n;i++) d[i][0]=a[i];
for(int j=1;(1<<j)<=n;j++){
for(int i=0;i+(1<<j)-1<n;i++){
d[i][j]=min(d[i][j-1],d[i+(1<<(j-1))][j-1]);
}
}
}
int query(int l,int r){
if(l>r) return INF;
int k=0;
while((1<<(k+1))<=r-l+1) k++;
return min(d[l][k],d[r-(1<<k)+1][k]);
}
int main(){
int t;
while(cin>>t){
while(t--){
cin>>n;
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
}
RMQ_init();
int m,l,r;
cin>>m;
for(int i=0;i<m;i++){
scanf("%d %d",&l,&r);
l--;r--;
if(l == r){
printf("%d\n",a[l]);
continue;
}
int temp=a[l];
l++;
while(l<=r){
int ll=l,rr=r;
bool bool1=true;
while(ll<rr){
int mid=(ll+rr)/2;
if(query(ll,mid)<=temp){
rr=mid;
}
else if(query(mid+1,rr)<=temp){
ll=mid+1;
}
else {
bool1=false;
break;
}
if(!bool1){
break;
}
}
if(!bool1){
break;
}
temp%=a[ll];
l=ll+1;
}
printf("%d\n",temp);
}
}
}
return 0;
}