rmq-st算法(hdu 5875)

題目: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


發佈了59 篇原創文章 · 獲贊 3 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章