題意:一個區間,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;
}