• 高橋君とホテル / Tak and Hotels


    高橋君とホテル / Tak and Hotels


    Time limit : 3sec / Stack limit : 256MB / Memory limit : 256MB

    Score : 700 points

    Problem Statement

    N hotels are located on a straight line. The coordinate of the i-th hotel (1≤iN) is xi.

    Tak the traveler has the following two personal principles:

    • He never travels a distance of more than L in a single day.
    • He never sleeps in the open. That is, he must stay at a hotel at the end of a day.

    You are given Q queries. The j-th (1≤jQ) query is described by two distinct integers aj and bj. For each query, find the minimum number of days that Tak needs to travel from the aj-th hotel to the bj-th hotel following his principles. It is guaranteed that he can always travel from the aj-th hotel to the bj-th hotel, in any given input.

    Constraints

    • 2≤N≤105
    • 1≤L≤109
    • 1≤Q≤105
    • 1≤xi<x2<…<xN≤109
    • xi+1−xiL
    • 1≤aj,bjN
    • ajbj
    • N, L, Q, xi, aj, bj are integers.

    Partial Score

    • 200 points will be awarded for passing the test set satisfying N≤103 and Q≤103.

    Input

    The input is given from Standard Input in the following format:

    N
    x1 x2  xN
    L
    Q
    a1 b1
    a2 b2
    :
    aQ bQ
    

    Output

    Print Q lines. The j-th line (1≤jQ) should contain the minimum number of days that Tak needs to travel from the aj-th hotel to the bj-th hotel.


    Sample Input 1

    9
    1 3 6 13 15 18 19 29 31
    10
    4
    1 8
    7 3
    6 7
    8 5
    

    Sample Output 1

    4
    2
    1
    2

    For the 1-st query, he can travel from the 1-st hotel to the 8-th hotel in 4 days, as follows:

    • Day 1: Travel from the 1-st hotel to the 2-nd hotel. The distance traveled is 2.
    • Day 2: Travel from the 2-nd hotel to the 4-th hotel. The distance traveled is 10.
    • Day 3: Travel from the 4-th hotel to the 7-th hotel. The distance traveled is 6.
    • Day 4: Travel from the 7-th hotel to the 8-th hotel. The distance traveled is 10.

    分析:对于每个点二分可以找到一天所能到达的最右和最左端点;

       然后关键就是倍增,这样每个小问题就可以在log复杂度解决了;

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <algorithm>
    #include <climits>
    #include <cstring>
    #include <string>
    #include <set>
    #include <map>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <list>
    #define rep(i,m,n) for(i=m;i<=n;i++)
    #define rsp(it,s) for(set<int>::iterator it=s.begin();it!=s.end();it++)
    #define mod 1000000000
    #define inf 0x3f3f3f3f
    #define vi vector<int>
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    #define ll long long
    #define pi acos(-1.0)
    #define pii pair<int,int>
    #define Lson L, mid, rt<<1
    #define Rson mid+1, R, rt<<1|1
    const int maxn=1e5+10;
    using namespace std;
    ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);}
    ll qpow(ll p,ll q){ll f=1;while(q){if(q&1)f=f*p;p=p*p;q>>=1;}return f;}
    int n,m,k,t,l[30][maxn],r[30][maxn];
    ll a[maxn],p;
    void init()
    {
        memset(l,-1,sizeof l);
        memset(r,-1,sizeof r);
        for(int i=0;i<=n-1;i++)
        {
            r[0][i]=lower_bound(a,a+n,a[i]+p)-a;
            if(r[0][i]==n||a[r[0][i]]>a[i]+p)r[0][i]--;
            l[0][i]=lower_bound(a,a+n,a[i]-p)-a;
            if(i==n-1)r[0][i]=-1;
            if(i==0)l[0][i]=-1;
        }
        for(int i=1;i<=29;i++)
        {
            for(int j=0;j<=n-1;j++)
            {
                if(r[i-1][j]<n-1)r[i][j]=r[i-1][r[i-1][j]];
                if(l[i-1][j]>0)l[i][j]=l[i-1][l[i-1][j]];
            }
        }
    }
    int main()
    {
        int i,j;
        scanf("%d",&n);
        rep(i,0,n-1)scanf("%lld",&a[i]);
        scanf("%lld",&p);
        init();
        int q;
        scanf("%d",&q);
        while(q--)
        {
            int b,c,ans=0;
            scanf("%d%d",&b,&c);
            b--,c--;
            if(b<c)
            {
                for(i=29;i>=0;i--)
                {
                    if(r[i][b]!=-1&&r[i][b]<=c)
                    {
                        ans+=qpow(2,i);
                        b=r[i][b];
                        if(b==c)break;
                    }
                }
                if(i==-1)ans++;
            }
            else
            {
                for(i=29;i>=0;i--)
                {
                    if(l[i][b]!=-1&&l[i][b]>=c)
                    {
                        ans+=qpow(2,i);
                        b=l[i][b];
                        if(b==c)break;
                    }
                }
                if(i==-1)ans++;
            }
            printf("%d
    ",ans);
        }
        //system("Pause");
        return 0;
    }
  • 相关阅读:
    orm 对象关系映射 指 表与类之间的映射 # 40
    事务 视图 触发器 函数 (内置) 存储过程 流程控制 索引 # 39
    exist 存在 Python操作mysql pymysql sql注入问题 # 38
    基本查询语句与方法 多表查询 # 37
    外键 #36
    存储引擎 索引 数据类型 约束条件 # 35
    mysql安装 登录 修改密码 库,表,记录(增删改查) # 34
    进程池和线程池 协程 # 33
    GIL全局解释器锁
    # 并发编程 -进程理论-进程的方法
  • 原文地址:https://www.cnblogs.com/dyzll/p/5816213.html
Copyright © 2020-2023  润新知