(CodeForces) J - Shopping Gym - 101201J (线段树+取模)

题意:每次给你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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值