You are given an array AA of NN postive integers, and MM queries in the form (l,r)(l,r). A function F(l,r) (1≤l≤r≤N)F(l,r) (1≤l≤r≤N) is defined as:
F(l,r)={AlF(l,r−1) modArl=r;l<r.F(l,r)={All=r;F(l,r−1) modArl<r.
You job is to calculate F(l,r)F(l,r), for each query (l,r)(l,r).
InputThere are multiple test cases.
The first line of input contains a integer TT, indicating number of test cases, and TT test cases follow.
For each test case, the first line contains an integer N(1≤N≤100000)N(1≤N≤100000).
The second line contains NN space-separated positive integers: A1,…,AN (0≤Ai≤109)A1,…,AN (0≤Ai≤109).
The third line contains an integer MM denoting the number of queries.
The following MM lines each contain two integers l,r (1≤l≤r≤N)l,r (1≤l≤r≤N), representing a query.OutputFor each query(l,r)(l,r), output F(l,r)F(l,r) on one line.
Sample Input
1 3 2 3 3 1 1 3
Sample Output
2
题意:
已知a[]数组,现在给出m组l,r。求a[l]%a[l+1]%a[l+2]%...a[r]的结果。
思路:
a[l]<a[l+1],那么这个膜运算是可以忽视的。单调队列,逆序预处理出每一个a[]的右边第一个小于a[]的数的位置R[],然后就是用a[l]%a[R[l]]%a[R[R[l]]]...。
#include<cstdio> #include<cstdlib> #include<iostream> #include<cstring> #include<algorithm> using namespace std; const int maxn=1000010; int a[maxn],R[maxn]; int main() { int n,m,T,i,j,l,r,t,ans; scanf("%d",&T); while(T--){ scanf("%d",&n); for(i=1;i<=n;i++) scanf("%d",&a[i]); for(i=1;i<=n+1;i++) R[i]=n+1; a[n+1]=0; for(i=n-1;i>=1;i--){ t=i; while(t<n){ // 得到R数组 if(a[t+1]<a[i]){ R[i]=t+1; break;} if(a[R[t+1]]>=a[i]) t=R[t+1]; else { for(j=t+1;j<=R[t+1];j++) {//这里可以二分优化 if(a[j]<a[i]) { R[i]=j;break; } } break; } } } scanf("%d",&m); while(m--){ scanf("%d%d",&l,&r); ans=a[l];t=l; while(R[t]<=r){ //过滤掉无用的膜运算 t=R[t]; ans%=a[t]; } printf("%d\n",ans); } } return 0; }