HDU 5875 Function

来源:互联网 发布:停车位软件哪个好 编辑:程序博客网 时间:2024/05/21 19:48

主要是线段树上的二分,线段树存区间最小值
每次找小于等于p的值,先在左边找,然后在右找,l,r为要找的区间
找到之后,该值的位置设为pos,P模上这个值,然后再找pos+1,r,直到找不到就输出就完了

#include <algorithm>#include <iostream>#include <cstring>#include <cstdlib>#include <vector>#include <cstdio>#include <bitset>#include <cmath>#include <queue>#include <stack>#include <map>#include <set>#define LL long long  #define lson l,mid,rt<<1  #define rson mid+1,r,rt<<1|1  using namespace std;  const int maxn=1e5+7;int sum[maxn<<2];int a[maxn];int x,y,n,m,t;void pushup(int rt){    sum[rt]=min(sum[rt<<1],sum[rt<<1|1]);  }void build(int l,int r,int rt){      if(l==r){          scanf("%d",&sum[rt]);          a[l]=sum[rt];        return;    }      int mid=(r+l)>>1;      build(lson);      build(rson);      pushup(rt);  }  int query(int l,int r,int ll,int rr,int rt,int k){      if(sum[rt]>k) return rr+1;    int mid=(r+l)>>1,res;    if(ll<=l&&rr>=r){        if(l==r) return l;        if(sum[rt<<1]<=k) return query(l,mid,ll,rr,rt<<1,k);        else return query(mid+1,r,ll,rr,rt<<1|1,k);    }    if(ll<=mid){        res=query(l,mid,ll,rr,rt<<1,k);        if(res<=rr) return res;    }    if(rr>mid){        res=query(mid+1,r,ll,rr,rt<<1|1,k);        if(res<=rr) return res;    }    return rr+1;}int main(){      scanf("%d",&t);    while(t--){        scanf("%d",&n);        build(1,n,1);        scanf("%d",&m);        while(m--){            scanf("%d%d",&x,&y);            int ans=a[x];            while(x<y){                int q=query(1,n,x+1,y,1,ans);                if(q<=y) ans%=a[q];                x=q;            }            printf("%d\n",ans);        }    }}