0%

2026 杭电春季联赛 4——1005-列车停放站(倍增法+右端点贪心)

题目大意

题目描述
给定 nn 辆列车的停放区间 [l,r][l, r]
mm 次询问,每次询问给出一个空区间 [x,y][x, y],需要求出在该空区间内最多可以完整停放多少辆列车。
被选择停放的列车区间必须完全包含在询问区间 [x,y][x, y] 内,且不同列车的停放区间在内部不能重叠,但端点可以相交(即列车之间可以紧贴,不留空隙)。

输入格式
第一行输入一个整数 TT1T51 \le T \le 5),表示测试数据组数。
对于每组数据:
第一行输入一个整数 nn1n1051 \le n \le 10^5),表示列车数量。
接下来 nn 行,每行输入两个整数 l,rl, r1l<r1091 \le l < r \le 10^9),表示一辆列车的停放区间为 [l,r][l, r]
接下来一行输入一个整数 mm1m1051 \le m \le 10^5),表示询问次数。
接下来 mm 行,每行输入两个整数 x,yx, y1x<y1091 \le x < y \le 10^9),表示每次询问的空区间。

输出格式
对于每次询问,输出一行一个整数,表示最多可以在该区间内停放的列车数量。

样例数据

样例输入

1
2
3
4
5
6
7
8
1
3
1 3
1 4
3 4
2
1 3
1 4

样例输出

1
2
1
2

样例解释
在该样例中,共有 33 辆列车,区间分别为 [1,3][1, 3][1,4][1, 4][3,4][3, 4]

  • 第一次询问区间 [1,3][1, 3]:只有第 11 辆列车 [1,3][1, 3] 能够完整停放在该区间内,因此最多停放 11 辆列车。

  • 第二次询问区间 [1,4][1, 4]:可以选择第 11 辆列车 [1,3][1, 3] 和第 33 辆列车 [3,4][3, 4]。这两辆列车在端点 33 处紧贴,且都完整包含在询问区间 [1,4][1, 4] 内,不发生重叠,因此最多停放 22 辆列车。

思路讲解

PDF

2025 United Kingdom and Ireland Programming Contest (UKIEPC 2025) 2025 英国 ICPC——B. Brickwork(判断砖块是否重叠)(扫描线的本质就是遍历一个出一个)(维护一个当前生效的集合)(把二维的问题变为一维的问题来做)

这道题目只要维护一个不相交集合,判断相交即可,而我们这道题目还需整一个这个选择哪些列车摆进来的决策,还是有点难度的。

哈哈,其实这道题目反其道而行之,这道题目的做法是倍增

image

说白了,就是我一次性不放一辆车改为放好多辆车

倍增表使用如下方法生成:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void gen_nxt() {
nxt.resize(liSZ, vector<int>(lgSZ + 1, INF));
// 我们可不可以,就是对于每一个位置,我们都能知道,他跳 1<<i 辆列车,可以跳到的 r 点
for (int lay = 0; lay <= lgSZ; ++lay) {
for (int i = 0; i < liSZ; ++i) {
if (lay == 0) {
nxt[i][lay] = dp_mn_r[i];
} else {
if (nxt[i][lay - 1] == INF) continue;
nxt[i][lay] = nxt[nxt[i][lay - 1]][lay - 1];
}
}
}
}

回答也使用这个倍增方法,直接搞出来:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int reply_query(int bg, int ed) {
auto [ok,l,r] = compress.projectLr(bg, ed);
if (!ok) return 0;
int cur = l;
int res = 0;
for (int lay = lgSZ; lay >= 0; --lay) {
if (nxt[cur][lay] <= r) {
cur = nxt[cur][lay];
res += (1 << lay);
}
}
return res;
}

AC代码

AC
https://acm.hdu.edu.cn/contest/view-code?cid=1200&rid=14607

心路历程(WA,TLE,MLE……)