传送门
中文题目就不在阐述题意
比赛时我们用分块来解决的,但是T掉了。。。
思路:我们使用单调栈维护的每个点可以跳跃到的下一个点,相当于两个点之间可以建一条边(如果不存在下一个点,可以和一个虚拟根结点建边),最后利用倍增求LCA的思想将L,不断向上跳跃,直到不能继续时,当前位置就是最后的位置,两个位置的深度差值就是答案。
///还有一种解法值 单调栈+树状数组+离线
代码:
///#include<bits/stdc++.h>
///#include<unordered_maps>
///#include<unordered_set>
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<bitset>
#include<set>
#include<stack>
#include<map>
#include<list>
#include<new>
#include<vector>
#define MT(a, b) memset(a,b,sizeof(a));
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double pai = acos(-1.0);
const double E = 2.718281828459;
const ll mod = 1000000007;
const int INF = 0x3f3f3f3f;
template<class T>
inline bool scan_d(T &ret) {
char c;
int sgn;
if (c = getchar(), c == EOF) return 0;
while (c != '-' && (c < '0' || c > '9')) c = getchar();
sgn = (c == '-') ? -1 : 1;
ret = (c == '-') ? 0 : (c - '0');
while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
ret *= sgn;
return 1;
}
int n, op;
int num[100005];
struct node {
int e;
int p;
} load[100005];
int head[100005], sign;
inline void add_edge(int s, int e) {
load[++sign] = node{e, head[s]};
head[s] = sign;
}
int depth[100005];
int grand[100005][20], N;
void dfs(int s) {
for (int i = 1; i <= N; i++) {
grand[s][i] = grand[grand[s][i - 1]][i - 1];
}
for (int i = head[s], e; ~i; i = load[i].p) {
e = load[i].e;
depth[e] = depth[s] + 1;
grand[e][0] = s;
dfs(e);
}
}
///初始化
inline void init() {
N = log2(n);
sign = depth[n + 1] = 0;
head[n + 1] = -1;
memset(grand, 0, sizeof(grand));
}
int q[100005]; ///单调栈
int main() {
int t, s, e;
scan_d(t);
while (t--) {
scan_d(n), scan_d(op);
init();
for (int i = 1; i <= n; i++) {
scan_d(num[i]);
head[i] = -1;
}
for (int i = n, top = 0; i >= 1; i--) {
while (top != 0 && num[q[top]] <= num[i]) top--;
if (top == 0) add_edge(n + 1, i);
else add_edge(q[top], i);
q[++top] = i;
}
dfs(n + 1);
while (op--) {
scan_d(s), scan_d(e);
int l = s;
for (int i = N; i >= 0; i--) {
if (grand[s][i] && grand[s][i] <= e && s <= e)
s = grand[s][i];
}
printf("%d\n", depth[l] - depth[s] + 1);
}
}
return 0;
}