CodeForces - 689D Friends and Subsequences ST表+二分

題目鏈接:https://codeforces.com/problemset/problem/689/D

題意:有多少區間[l, r]滿足,max(al..ar) = min(bl..br)

題解:對於先固定l,那麼對於max(a),是一個遞增的序列,對於min(b)是一個遞減的序列,因此我們就可以二分確定出,第一個符合條件的位置和最後一個符合條件的位置

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 200100;
int a[N], b[N];
int dp1[N][22], dp2[N][22];
int n;
int getmax(int l, int r) {
	int k = log2(r - l + 1);
	return max(dp1[l][k], dp1[r - (1 << k) + 1][k]);
}
int getmin(int l, int r) {
	int k = log2(r - l + 1);
	return min(dp2[l][k], dp2[r - (1 << k) + 1][k]);
}
int low(int pos) {
	int ans = -1;
	int cnt1, cnt2;
	int l = pos, r = n, mid;
	while(l <= r) {
		mid = (l + r) >> 1;
		cnt1 = getmax(pos, mid);
		cnt2 = getmin(pos, mid);
		if(cnt1 > cnt2) r = mid - 1;
		else if(cnt1 < cnt2) l = mid + 1;
		else {
			ans = mid;
			r = mid - 1;
		}
	}
	return ans;
}
int upp(int pos) {
	int ans = -1;
	int cnt1, cnt2;
	int l = pos, r = n, mid;
	while(l <= r) {
		mid = (l + r) >> 1;
		cnt1 = getmax(pos, mid);
		cnt2 = getmin(pos, mid);
		if(cnt1 > cnt2) r = mid - 1;
		else if(cnt1 < cnt2) l = mid + 1;
		else {
			ans = mid;
			l = mid + 1;
		}
	}
	if(ans == -1) return -2;
	else return ans;
}
int main() {
	ll ans = 0;
	scanf("%d", &n);
	for(int i = 1; i <= n; i++) scanf("%d", &a[i]), dp1[i][0] = a[i];
	for(int i = 1; i <= n; i++) scanf("%d", &b[i]), dp2[i][0] = b[i];
	for(int i = 1; i < 22; i++)
		for(int j = 1; j + (1 << i) - 1 <= n; j++)
			dp1[j][i] = max(dp1[j][i - 1], dp1[j + (1 << (i - 1))][i - 1]);
	for(int i = 1; i < 22; i++)
		for(int j = 1; j + (1 << i) - 1 <= n; j++)
			dp2[j][i] = min(dp2[j][i - 1], dp2[j + (1 << (i - 1))][i - 1]);
	for(int i = 1; i <= n; i++) {
		ans += upp(i) - low(i) + 1;
	}
	cout << ans << endl;
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章