样例 1
输入:
6
1 2 3 2 1 4
6 7 1 2 3 2
输出:
2
备注
1≤n≤10^6,1≤ai,bi≤10^9。
思路:
(1)使用ST表。
ST表(Sparse Table)是一种用于高效处理区间查询的数据结构。它可以在O(1)的时间复杂度内回答某一区间的最值查询(最小值、最大值等)。ST表使用动态规划的思想,通过预处理的方式来快速计算出各个区间的最值。
(2)使用二分。因为此题具有单调性:随着放入数组的数越多,最大值一定非递减。最小值一定非递增。如果固定右端点r,则向左看,最大值从l->r呈阶梯状递增,最小值从l->r呈阶梯状递减,其中一定有交点使最小值=最大值。因为是阶梯状递增和递减,所以交点为横着的一条线段,即l的范围为此线段的范围。
所以每次枚举r,找l的范围并保存在答案中。找l的范围即找max=min,用二分来找。
此题代码:
#include <bits/stdc++.h> using namespace std; const int N = 1e6 + 10; int n, a[N], b[N], mn[N][20], mx[N][20], Lg[N], l, r, mid, ans; void pre() { Lg[1] = 0; for (int i = 2; i <= n; i++) { Lg[i] = Lg[i >> 1] + 1; } } void ST_create() { // 创建ST表 for (int i = 1; i <= n; i++) { mx[i][0] = a[i], mn[i][0] = b[i]; } for (int j = 1; j <= Lg[n]; j++) { for (int i = 1; i <= n - (1 << j) + 1; i++) { mx[i][j] = max(mx[i][j - 1], mx[i + (1 << (j - 1))][j - 1]); mn[i][j] = min(mn[i][j - 1], mn[i + (1 << (j - 1))][j - 1]); } } } int ST_qmax(int l, int r) { // ST表求max int k = Lg[r - l + 1]; return max(mx[l][k], mx[r - (1 << k) + 1][k]); } int ST_qmin(int l, int r) { // ST表求min int k = Lg[r - l + 1]; return min(mn[l][k], mn[r - (1 << k) + 1][k]); } int findl(int i) { // l的范围左边界 int l = 1, r = i, mid, ans = 0, minn, maxn; while (l <= r) { mid = (l + r) / 2; maxn = ST_qmax(mid, i), minn = ST_qmin(mid, i); if (maxn <= minn) { ans = mid, r = mid - 1; } else l = mid + 1; } return ans; } int findr(int i) // i为固定的枚举的右边界 { // l的范围右边界 int l = 1, r = i, mid, ans = 0, minn, maxn; while (l <= r) // 二分 { mid = (l + r) / 2; maxn = ST_qmax(mid, i), minn = ST_qmin(mid, i); if (maxn >= minn) { ans = mid, l = mid + 1; } else r = mid - 1; } return ans; } int main() { cin >> n; for (int i = 1; i <= n; i++) cin >> a[i]; for (int i = 1; i <= n; i++) cin >> b[i]; pre(); ST_create(); for (int i = 1; i <= n; i++) { // 枚举右端点i // 对于每个i,求l的范围findl和findr int j = findl(i); if (j < 1 || j > i) { continue; } int k = findr(i); ans += k - j + 1; } cout << ans; return 0; }