给n个数,再给q次询问,每次询问回答区间[l,r]的a[l]%a[l+1]%a[l+2]%a[l+3]....%a[r]的答案。
可以知道只有当一个数遇到一个比它小的数答案才会改变且取模最多log次就会停止,所以用线段树暴力寻找一个数右边第一个比它小的数即可。
#include <bits/stdc++.h> #define pb push_back #define mp make_pair #define fi first #define se second #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define up rt,rt<<1,rt<<1|1 #define mem(x) memset(x,0,sizeof(x)) #define mem1(x) memset(x,-1,sizeof(x)) using namespace std; typedef long long ll; typedef double db; const int M = 1e5+7; const double pi = acos(-1); const int inf = 2147483647; const int mod = 1e9+7; int _,n,q,a[M],tmp; int mn[M<<2]; void pushup(int rt,int l,int r){ mn[rt]=min(mn[l],mn[r]); } void build(int l,int r,int rt){ if(l==r){ mn[rt]=a[l]; return ; } int mid=(l+r)>>1; build(lson); build(rson); pushup(up); } int query(int L,int R,int l,int r,int rt){//找一个数右边第一个比它小的数 if(L<=l&&r<=R){ if(l==r) return l; int mid=(l+r)>>1; if(mn[rt<<1]<=tmp) return query(L,R,lson); else if(mn[rt<<1|1]<=tmp) return query(L,R,rson); else return 1000000; } int mid=(l+r)>>1,ans=1e6; if(L<=mid&&mn[rt<<1]<=tmp) ans=min(query(L,R,lson),ans); if(R>mid&&mn[rt<<1|1]<=tmp) ans=min(ans,query(L,R,rson)); return ans; } int main(){ #ifdef LMissher freopen("1.in","r",stdin); freopen("1.out","w",stdout); #endif scanf("%d",&_); while(_--){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); build(1,n,1); scanf("%d",&q); while(q--){ int l,r; scanf("%d%d",&l,&r); tmp=a[l]; while((l=query(l+1,r,1,n,1))<=r){ tmp%=a[l]; } printf("%d\n",tmp); } } return 0; }