题意:每次给你v ,l,r,让你将v逐个对区间l~r的数取模,求最后结果。
解:对于一个数取模,那只有模数小于等于它取模才有意义,要不然取模的结果还是它本身,所以我们取区间中第一个小于等于该数的,并从他的位置向后继续找,因为取模每次下降一半,然后找区间小于该数最先出现的线段树即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+7;
ll a[N];
ll mi[4*N];
int n,q;
void pushup(int rt) {
mi[rt]=min(mi[rt<<1],mi[rt<<1|1]);
}
void build(int rt,int l,int r) {
if(l==r) {
mi[rt]=a[l];
// cout<<l<<" "<<r<<" :"<<a[l]<<endl;
return;
}
int mid=(l+r)>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
pushup(rt);
}
struct node{
ll id,w;
}tp,qu;
void query(int rt,int l,int r,int L,int R,ll X) {
if(mi[rt]>X) return;
if(r<L || R<l) return;
if(l==r){
// cout<<rt<<" "<<l<<" "<<r<<" :"<<mi[rt]<<endl;
qu={l,mi[rt]};
return;
}
int mid=(l+r)>>1;
if(mi[rt<<1]<=X && L<=mid){
query(rt<<1,l,mid,L,R,X);
}
if(qu.id!=0 && qu.w!=0) return;
if(mi[rt<<1|1]<=X && R>mid){
query(rt<<1|1,mid+1,r,L,R,X);
}
}
ll check(ll v,int l,int r) {
int L=l,R=r;
ll nv=v;
while(L<=R){
qu={0,0};
query(1,1,n,L,R,nv);
// cout<<qu.id<<" "<<qu.w<<endl;
if(qu.id==0 && qu.w==0){
break;
}
else{
nv%=qu.w;
if(nv==0) return 0;
L=qu.id;
}
}
return nv;
}
int main() {
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++) {
scanf("%lld",&a[i]);
}
build(1,1,n);
while(q--) {
ll v;int l,r;
scanf("%lld%d%d",&v,&l,&r);
printf("%lld\n",check(v,l,r));
}
return 0;
}