P8251 丹钓战 题解
Yansuan_HCl · · 题解
记第
对于一个区间
因此,可以记录每个二元组能被哪个二元组弹出去。按题意模拟即可。
struct P { int a, b; };
// ...
static pair<P, int> s[500005];
int p = 0;
for (int i = 1; i <= n; ++i) {
while(p && (s[p].first.a == f[i].a || s[p].first.b <= f[i].b)) {
nxt[s[p].second] = i; // 记录这个二元组被谁弹出去了
--p;
}
s[++p] = {f[i], i};
}
此后,对于区间
可以使用倍增对跳的过程进行优化。记录
#include<bits/stdc++.h>
using namespace std;
template <typename T>
inline void read(T& s) {
char c = getchar();
T f = 1; s = 0;
while (c < '0' || c > '9') {
if (c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9') {
s = (s << 1) + (s << 3) + (c ^ 48);
c = getchar();
}
s *= f;
}
const int N = 500005;
struct P{ int a, b; } f[N];
int n,q;
int nxt[21][N];
int main(){
read(n); read(q);
for (int i = 1; i <= n; ++i) read(f[i].a);
for (int i = 1; i <= n; ++i) read(f[i].b);
static pair<P, int> s[500005]; int p = 0;
for (int i = 1; i <= n; ++i) {
while(p && (s[p].first.a == f[i].a || s[p].first.b <= f[i].b)) {
nxt[0][s[p].second] = i;
--p;
}
s[++p] = {f[i], i};
}
for (int i = 1; i <= 20; ++i) {
for (int j = 1; j <= n; ++j)
nxt[i][j] = nxt[i - 1][nxt[i - 1][j]]; // 处理倍增
}
while (q--){
int cnt = 0;
int l, r;
read(l); read(r);
for (int i = 20; i >= 0; --i) {
if (nxt[i][l] && nxt[i][l] <= r) { // 向右跳,但不越过边界
cnt += 1 << i; // 跳了 2^i 次
l = nxt[i][l];
}
}
printf("%d\n", cnt + 1); // 要算上 L 本身
}
return 0;
}
不需要任何高级数据结构。