题目链接
Problem Statement
There is a grid of squares with
H
+
1
H+1
H+1 horizontal rows and
W
W
W vertical columns.
You will start at one of the squares in the top row and repeat moving one square right or down. However, for each integer i i i from 1 1 1 through H H H, you cannot move down from the A i A_i Ai-th, ( A i + 1 ) (Ai+1) (Ai+1)-th, … \dots …, B i B_i Bi-th squares from the left in the i i i-th row from the top.
For each integer k k k from 1 1 1 through H H H, find the minimum number of moves needed to reach one of the squares in the ( k + 1 ) (k+1) (k+1)-th row from the top. (The starting square can be chosen individually for each case.) If, starting from any square in the top row, none of the squares in the ( k + 1 ) (k+1) (k+1)-th row can be reached, print − 1 -1 −1 instead.
Constraints
- 1 ≤ H , W ≤ 2 × 1 0 5 1≤H,W≤2×10^5 1≤H,W≤2×105
- 1 ≤ A i ≤ B i ≤ W 1≤A_i≤B_i≤W 1≤Ai≤Bi≤W
Input
Input is given from Standard Input in the following format:
H
H
H
W
W
W
A
1
A_1
A1
B
1
B_1
B1
A
2
A_2
A2
B
2
B_2
B2
.
.
_.^.
..
A
H
A_H
AH
B
H
B_H
BH
Output
Print
H
H
H lines. The
i
i
i-th line should contain the answer for the case
k
=
i
k=i
k=i.
Sample Input 1
4 4
2 4
1 1
2 3
2 4
Sample Output 1
1
3
6
-1
Let ( i , j ) (i,j) (i,j) denote the square at the i i i-th row from the top and j j j-th column from the left.
For k = 1 k=1 k=1, we need one move such as ( 1 , 1 ) → ( 2 , 1 ) (1,1) → (2,1) (1,1)→(2,1).
For k = 2 k=2 k=2, we need three moves such as ( 1 , 1 ) → ( 2 , 1 ) → ( 2 , 2 ) → ( 3 , 2 ) (1,1)→(2,1)→(2,2)→(3,2) (1,1)→(2,1)→(2,2)→(3,2).
For k = 3 k=3 k=3, we need six moves such as ( 1 , 1 ) → ( 2 , 1 ) → ( 2 , 2 ) → ( 3 , 2 ) → ( 3 , 3 ) → ( 3 , 4 ) → ( 4 , 4 ) (1,1)→(2,1)→(2,2)→(3,2)→(3,3)→(3,4)→(4,4) (1,1)→(2,1)→(2,2)→(3,2)→(3,3)→(3,4)→(4,4).
For k = 4 k=4 k=4, it is impossible to reach any square in the fifth row from the top.
建一棵线段树,位置
x
x
x的值
t
[
x
]
t[x]
t[x]为从第一行到第
i
i
i行需要在水平方向移动的最小距离。
n
o
w
now
now表示从第一行到能到达第
i
i
i行的列号的最小值。
对于第
i
i
i行,设第
i
−
1
i-1
i−1行禁止向下走的区间为
[
l
,
r
]
[l,r]
[l,r],则:
- 如果 n o w < l now< l now<l,则对于区间 [ l , r ] [l,r] [l,r],由于禁止向下走,不能直接从 i − 1 i-1 i−1行转移过来,而是从 ( i − 1 , l − 1 ) (i-1,l-1) (i−1,l−1)转移过来,对于 x ∈ [ l , r ] x\in[l,r] x∈[l,r], t [ x ] t[x] t[x]需要在 t [ l − 1 ] t[l-1] t[l−1]的基础上加上 x − l + 1 x-l+1 x−l+1。
- 如果 n o w ∈ [ l , r ] now\in [l,r] now∈[l,r],则第 i i i行位于区间 [ n o w , r ] [now,r] [now,r]内的所有点都不能到达,直接设为 ∞ \infty ∞,将 n o w now now设为 r + 1 r+1 r+1。
- 如果 n o w ∈ ( r , m ] now\in(r,m] now∈(r,m],则对结果无影响。
- 如果 n o w > m now>m now>m则不可到达第 i i i行, i i i行及后面都输出 − 1 -1 −1。
然后答案为线段树维护区间内的最小值。
时间复杂度为
O
(
H
log
W
)
O(H\log W)
O(HlogW)。
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
inline int qr() {
int f = 0, fu = 1;
char c = getchar();
while (c < '0' || c > '9') {
if (c == '-')fu = -1;
c = getchar();
}
while (c >= '0' && c <= '9') {
f = (f << 3) + (f << 1) + c - 48;
c = getchar();
}
return f * fu;
}
const int N = 2e5 + 10;
struct Seg_Tree {
struct T {
int l, r, ans, add;
} t[N * 4];
void build(int p, int l, int r) {
t[p].l = l, t[p].r = r, t[p].ans = t[p].add = 0;
if (l == r) return;
int mid = (l + r) >> 1;
build(p << 1, l, mid);
build(p << 1 | 1, mid + 1, r);
}
void spread(int p) {
if (t[p].add) {
t[p << 1].ans = t[p].l - t[p].add;
t[p << 1].add = t[p].add;
t[p << 1 | 1].ans = ((t[p].l + t[p].r) >> 1) + 1 - t[p].add;
t[p << 1 | 1].add = t[p].add;
t[p].add = 0;
}
}
void change(int p, int l, int r, int c) {
if (l <= t[p].l && t[p].r <= r) {
t[p].ans = t[p].l - c, t[p].add = c;
return;
}
spread(p);
int mid = (t[p].l + t[p].r) >> 1;
if (l <= mid)change(p << 1, l, r, c);
if (r > mid)change(p << 1 | 1, l, r, c);
t[p].ans = min(t[p << 1].ans, t[p << 1 | 1].ans);
}
int ask(int p, int x) {
if (t[p].l == t[p].r)return x - t[p].ans;
spread(p);
int mid = (t[p].l + t[p].r) >> 1;
return x <= mid ? ask(p << 1, x) : ask(p << 1 | 1, x);
}
} tr;
int n, m, now = 1;
int main() {
n = qr(), m = qr();
tr.build(1, 1, m);
for (int i = 1; i <= n; ++i) {
int l = qr(), r = qr();
if (now >= l && now <= r)tr.change(1, now, r, -INF), now = r + 1;
else if (now < l)tr.change(1, l, r, tr.ask(1, l - 1));
if (now > m) {
for (int j = i; j <= n; ++j)puts("-1");
return 0;
}
printf("%d\n", i + tr.t[1].ans);
}
return 0;
}