题目链接:https://atcoder.jp/contests/arc060/tasks/arc060_c
Problem Statement
NN hotels are located on a straight line. The coordinate of the ii-th hotel (1≤i≤N)(1≤i≤N) is xixi.
Tak the traveler has the following two personal principles:
- He never travels a distance of more than LL 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 QQ queries. The jj-th (1≤j≤Q)(1≤j≤Q) query is described by two distinct integers ajaj and bjbj. For each query, find the minimum number of days that Tak needs to travel from the ajaj-th hotel to the bjbj-th hotel following his principles. It is guaranteed that he can always travel from the ajaj-th hotel to the bjbj-th hotel, in any given input.
Constraints
- 2≤N≤1052≤N≤105
- 1≤L≤1091≤L≤109
- 1≤Q≤1051≤Q≤105
- 1≤xi<x2<...<xN≤1091≤xi<x2<...<xN≤109
- xi+1−xi≤Lxi+1−xi≤L
- 1≤aj,bj≤N1≤aj,bj≤N
- aj≠bjaj≠bj
- N,L,Q,xi,aj,bjN,L,Q,xi,aj,bj are integers.
Partial Score
- 200200 points will be awarded for passing the test set satisfying N≤103N≤103 and Q≤103Q≤103.
Input
The input is given from Standard Input in the following format:
NN x1x1 x2x2 ...... xNxN LL QQ a1a1 b1b1 a2a2 b2b2 : aQaQ bQbQ
Output
Print QQ lines. The jj-th line (1≤j≤Q)(1≤j≤Q) should contain the minimum number of days that Tak needs to travel from the ajaj-th hotel to the bjbj-th hotel.
Sample Input 1 Copy
Copy
9 1 3 6 13 15 18 19 29 31 10 4 1 8 7 3 6 7 8 5
Sample Output 1 Copy
Copy
4 2 1 2
For the 11-st query, he can travel from the 11-st hotel to the 88-th hotel in 44 days, as follows:
- Day 11: Travel from the 11-st hotel to the 22-nd hotel. The distance traveled is 22.
- Day 22: Travel from the 22-nd hotel to the 44-th hotel. The distance traveled is 1010.
- Day 33: Travel from the 44-th hotel to the 77-th hotel. The distance traveled is 66.
- Day 44: Travel from the 77-th hotel to the 88-th hotel. The distance traveled is 1010.
题意:
一条线上面有n个点和每步最多走的距离。q次询问,问你从ai到bi至少要走多少步,(题意保证有解)
思路:
dp[i][j]表示从第j个点走2的i次方次最远能到达的点。那么d[i][j]=d[i-1][d[i-1][j]];
代码:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll a[100009];
ll d[30][100009];
ll n,l,q;
void init()
{
for(int i=1; i<=20; i++)
{
for(int j=1; j<=n; j++)
{
d[i][j]=d[i-1][d[i-1][j]];
}
}
}
int main()
{
scanf("%lld",&n);
for(ll i=1; i<=n; i++)
{
scanf("%lld",&a[i]);
}
scanf("%lld%lld",&l,&q);
for(ll i=1; i<=n; i++)
{
ll z=i+1;
ll y=n;
while(z<=y)
{
ll mid=(z+y)/2;
if(a[mid]-a[i]<=l)
{
z=mid+1;
}
else
{
y=mid-1;
}
}
d[0][i]=z-1;
}
init();
ll a,b;
for(ll k=1;k<=q;k++)
{
ll tot=0;
scanf("%lld%lld",&a,&b);
if(a>b)
{
swap(a,b);
}
for(ll i=20;i>=0;i--)
{
if(d[i][a]<b)//这里找到的是最靠近b左边的点那么d[i+1][a]>=b。所以从d[i][a]这个点最
多走2^i-1次到最靠近b左边的点。而后面2^0+2^1+....2^(i-1)=2^-1.所以并没有用少讨论。
{
tot+=(1ll<<i);
a=d[i][a];
}
}
tot++;
cout<<tot<<endl;
}
}