hdu5875 Function

来源:互联网 发布:淘宝客服怎么应聘 编辑:程序博客网 时间:2024/05/20 09:44

题意:一个区间,m次询问(l,r),求a[l]%a[l+1]%...%a[r]

题解:比赛时候,想到的是二分线段树,说了以后,学弟说可能会退化,当时没多想,其实仔细想想,构造不出来那样的数据吧,线段树常数比较大,看到队友用RMQ,常数小

            其实本质差不多,就是先找前一半的最小,看看是不是小于a[l],如果是,就继续在左找,没有就在右找,如果右也没有,就退

int a[100010],n;int d[100010][30];void RMQ_init(){    for(int i=0;i<n;i++) d[i][0]=a[i];    for(int j=1;(1<<j)<=n;j++){        for(int i=0;i+(1<<j)-1<n;i++){            d[i][j]=min(d[i][j-1],d[i+(1<<(j-1))][j-1]);        }    }}int query(int l,int r){    if(l>r) return INF;    int k=0;    while((1<<(k+1))<=r-l+1) k++;    return min(d[l][k],d[r-(1<<k)+1][k]);}int main(){    int t;    while(cin>>t){    while(t--){        cin>>n;        for(int i=0;i<n;i++){            scanf("%d",&a[i]);        }        RMQ_init();        int m,l,r;        cin>>m;        for(int i=0;i<m;i++){            scanf("%d %d",&l,&r);            l--;r--;            if(l == r){                printf("%d\n",a[l]);                continue;            }            int temp=a[l];            l++;            while(l<=r){                int ll=l,rr=r;                bool bool1=true;                while(ll<rr){                    int mid=(ll+rr)/2;                    if(query(ll,mid)<=temp){                        rr=mid;                    }                    else if(query(mid+1,rr)<=temp){                        ll=mid+1;                    }                    else {                        bool1=false;                        break;                    }                    if(!bool1){                        break;                    }                }                if(!bool1){                    break;                }                temp%=a[ll];                l=ll+1;            }            printf("%d\n",temp);        }    }    }    return 0;}


0 0
原创粉丝点击