rmq-st算法<区间最大最小>(hdu 5875)

来源:互联网 发布:汉字域名百度收录吗 编辑:程序博客网 时间:2024/05/29 07:27

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5875

题意:给定一个数组,并给出[l,r],要求求出A(l)%A(l+1)%......%A(r)的值,当l==r时 直接等于A(l)

题解:这道题的意思就是每次找到区间内最靠近l的且比当前ans小的进行取模,每次都这么取,知道到r,可以利用rmq算法先用o(nlogn)进行预处理,然后查找时的复杂度就只有o(1),每次快速查找最靠近的最小值

代码:

#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>using namespace std;int dp[100050][25];void rmq(int num)//o(nlogA){    for(int j=1;(1<<j)<=num;j++)    {        for(int i=1;i<=num;i++)        {            if(i+(1<<j)-1<=num)            {                dp[i][j]=min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);            }        }    }}int query(int l,int r){    if(l>r) return 1000000005;    int len=r-l+1;    int k=0;    while((1<<(k+1))<=len) k++;    return min(dp[l][k],dp[r-(1<<(k))+1][k]);}int main(){    int t,m,q;    scanf("%d",&t);    while(t--)    {        scanf("%d",&m);        for(int i=1;i<=m;i++)        {            scanf("%d",&dp[i][0]);        }        rmq(m) ;        scanf("%d",&q);        for(int i=1;i<=q;i++)        {            int l,r;            scanf("%d %d",&l,&r);            int ans=dp[l][0];            bool flag=0;            if(l==r) {printf("%d\n",ans);continue;};            l++;            while(l<=r)            {                int left=l,right=r;                while(left<right)                {                    int mid=(left+right)/2;                    if(query(left,mid)<=ans) right=mid;                    else if(query(mid+1,right)<=ans) left=mid+1;                    else {flag=1;break;}                }                if(flag) break;                l=left;                ans%=dp[l][0];                l++;//必须加1,不然可以取自己            }            printf("%d\n",ans);        }    }    return 0;}

附录:

rmq-st算法:http://blog.csdn.net/niushuai666/article/details/6624672/

              http://blog.csdn.net/liang5630/article/details/7917702


0 0