CF689D Friends and Subsequences
阿新 • • 發佈:2021-10-31
題目大意
給定兩個大小為 \(n\) 的序列 \(a_i,b_i\),求有多少個數對 \((l,r)\),滿足 \(1\le l\le r\le n\) 且
\[\max_{i=l}^r a_i=\min_{i=l}^r b_i \]\(1 \le n\le 2\times 10^5\),\(|a_i|,|b_i|\le 10^9\)。
解題思路
ST
+ 二分。
首先考慮一個 \(\mathcal{O}(n^2)\) 演算法,不難想到,可以 \(\mathcal O(n \log n)\) 預處理 ST
表,然後暴力列舉 \((l,r)\) 看是否滿足要求。
我們把問題轉化一下,固定左界 \(l\)
不難發現這個東西是單調的滿足單調,所以直接二分 \(l'\) 和 \(r'\) 並判斷是否滿足要求,預處理可以用 ST
表完成,然後讓答案加上 \(r'-l'+1\) 即可。
時間複雜度 \(\mathcal O(n \log n+n \log n)\)。
CODE
#include <bits/stdc++.h> #define int long long using namespace std; int a[200086]; int b[200086]; int mmax[200086][20]; int mmin[200086][20]; int Max(int l, int r) { if (l > r) swap(l, r); int k = log2(r - l + 1); return max(mmax[l][k], mmax[r - (1 << k) + 1][k]); } int Min(int l, int r) { if (l > r) swap(l, r); int k = log2(r - l + 1); return min(mmin[l][k], mmin[r - (1 << k) + 1][k]); } int findl(int l, int r, int n) { int left = l; while (l <= r) { int mid = (l + r) / 2; if (Max(left, mid) < Min(left, mid)) l = mid + 1; else r = mid - 1; } if (l <= n && Max(left, l) == Min(left, l)) return l; else return 0; } int findr(int l, int r, int n) { int left = l; while (l <= r) { int mid = (l + r) / 2; if (Max(left, mid) > Min(left, mid)) r = mid - 1; else l = mid + 1; } if (r >= 1 && Max(left, r) == Min(left, r)) return r; else return 0; } int n; signed main() { scanf("%lld", &n); for (int i = 1; i <= n; i++) scanf("%lld", &a[i]); for (int i = 1; i <= n; i++) scanf("%lld", &b[i]); for (int i = 1; i <= n; i++) mmax[i][0] = a[i]; for (int i = 1; i <= n; i++) mmin[i][0] = b[i]; for (int k = 1; (1 << k) <= n; k++) for (int i = 1; i + (1 << k) - 1 <= n; i++) mmax[i][k] = max(mmax[i][k - 1], mmax[i + (1 << (k - 1))][k - 1]); for (int k = 1; (1 << k) <= n; k++) for (int i = 1; i + (1 << k) - 1 <= n; i++) mmin[i][k] = min(mmin[i][k - 1], mmin[i + (1 << (k - 1))][k - 1]); int cnt = 0; for (int i = 1; i <= n; i++) { int l = findl(i, n, n); int r = findr(i, n, n); if (l != 0 && r != 0) { if (l > r) swap(l, r); int ans = (r - l + 1); cnt += ans; } } printf("%lld\n", cnt); return 0; }
本文來自部落格園,作者:蒟蒻orz,轉載請註明原文連結:https://www.cnblogs.com/orzz/p/15489288.html