[CF689D] Friends and Subsequences(RMQ, 二分)

题目链接:http://codeforces.com/contest/689/problem/D

题意:给出两个数列a,b,问有多少个下标相同的区间,使该区间内a的最大值等于b的最小值。

预处理出a,b每个区间内的最大值或最小值,之后枚举每一个位置,由于min[l,r]>=min[l,r+1],max[l,r]<=max[l,r+1],根据这个性质我们可以二分枚举两个序列中从i除法a的最大值等于b的最小值的右端点,用lower_bound和upper_bound可以确定这个右端点的范围,即右端点在这个范围内无论如何取结果都成立,所以这个区间的子区间个数为[r-l+1]。

  1 /*
  2 ━━━━━┒ギリギリ♂ eye!
  3 ┓┏┓┏┓┃キリキリ♂ mind!
  4 ┛┗┛┗┛┃\○/
  5 ┓┏┓┏┓┃ /
  6 ┛┗┛┗┛┃ノ)
  7 ┓┏┓┏┓┃
  8 ┛┗┛┗┛┃
  9 ┓┏┓┏┓┃
 10 ┛┗┛┗┛┃
 11 ┓┏┓┏┓┃
 12 ┛┗┛┗┛┃
 13 ┓┏┓┏┓┃
 14 ┃┃┃┃┃┃
 15 ┻┻┻┻┻┻
 16 */
 17 #include <algorithm>
 18 #include <iostream>
 19 #include <iomanip>
 20 #include <cstring>
 21 #include <climits>
 22 #include <complex>
 23 #include <fstream>
 24 #include <cassert>
 25 #include <cstdio>
 26 #include <bitset>
 27 #include <vector>
 28 #include <deque>
 29 #include <queue>
 30 #include <stack>
 31 #include <ctime>
 32 #include <set>
 33 #include <map>
 34 #include <cmath>
 35 using namespace std;
 36 #define fr first
 37 #define sc second
 38 #define cl clear
 39 #define BUG puts("here!!!")
 40 #define W(a) while(a--)
 41 #define pb(a) push_back(a)
 42 #define Rint(a) scanf("%d", &a)
 43 #define Rs(a) scanf("%s", a)
 44 #define Cin(a) cin >> a
 45 #define FRead() freopen("in", "r", stdin)
 46 #define FWrite() freopen("out", "w", stdout)
 47 #define Rep(i, len) for(int i = 0; i < (len); i++)
 48 #define For(i, a, len) for(int i = (a); i < (len); i++)
 49 #define Cls(a) memset((a), 0, sizeof(a))
 50 #define Clr(a, x) memset((a), (x), sizeof(a))
 51 #define Full(a) memset((a), 0x7f7f7f, sizeof(a))
 52 #define lrt rt << 1
 53 #define rrt rt << 1 | 1
 54 #define pi 3.14159265359
 55 #define RT return
 56 #define lowbit(x) x & (-x)
 57 #define onecnt(x) __builtin_popcount(x)
 58 typedef long long LL;
 59 typedef long double LD;
 60 typedef unsigned long long ULL;
 61 typedef pair<int, int> pii;
 62 typedef pair<string, int> psi;
 63 typedef pair<LL, LL> pll;
 64 typedef map<string, int> msi;
 65 typedef vector<int> vi;
 66 typedef vector<LL> vl;
 67 typedef vector<vl> vvl;
 68 typedef vector<bool> vb;
 69 
 70 const int maxn = 200200;
 71 int dp[maxn][20][2];
 72 
 73 void st(int* a, int* b, int n) {
 74     for(int i = 1; i <= n; i++) dp[i][0][0] = b[i], dp[i][0][1] = a[i];
 75     for(int j = 1; (1 << j) - 1 <= n; j++) {
 76         for(int i = 1; i + (1 << j) - 1 <= n; i++) {
 77             dp[i][j][0] = min(dp[i][j-1][0], dp[i+(1<<(j-1))][j-1][0]);
 78             dp[i][j][1] = max(dp[i][j-1][1], dp[i+(1<<(j-1))][j-1][1]);
 79         }
 80     }
 81 }
 82 
 83 int query(int l, int r) {
 84     int k = int(log(r-l+1) / log(2.0));
 85     return max(dp[l][k][1], dp[r-(1<<k)+1][k][1]) - min(dp[l][k][0], dp[r-(1<<k)+1][k][0]);
 86 }
 87 
 88 int n;
 89 int a[maxn], b[maxn];
 90 
 91 int lower(int x) {
 92     int lo = x, hi = n;
 93     int ret = n;
 94     while(lo <= hi) {
 95         int mid = (lo + hi) >> 1;
 96         int cur = query(x, mid);
 97         if(cur > 0) hi = mid - 1;
 98         else if(cur < 0) lo = mid + 1;
 99         else {
100             ret = min(ret, mid);
101             hi = mid - 1;
102         }
103     }
104     return ret;
105 }
106 
107 int upper(int x) {
108     int lo = x, hi = n;
109     int ret = -1;
110     while(lo <= hi) {
111         int mid = (lo + hi) >> 1;
112         int cur = query(x, mid);
113         if(cur > 0) hi = mid - 1;
114         else if(cur < 0) lo = mid + 1;
115         else {
116             ret = max(ret, mid);
117             lo = mid + 1;
118         }
119     }
120     return ret;
121 }
122 
123 int main() {
124     // FRead();
125     while(~Rint(n)) {
126         For(i, 1, n+1) Rint(a[i]);
127         For(i, 1, n+1) Rint(b[i]);
128         st(a, b, n);
129         LL ret = 0;
130         For(i, 1, n+1) {
131             int lo = lower(i);
132             int hi = upper(i);
133             if(lo <= hi) ret += hi - lo + 1;
134         }
135         cout << ret << endl;
136     }
137     RT 0;
138 }
原文地址:https://www.cnblogs.com/kirai/p/5809792.html