题干:
Mike and !Mike are old childhood rivals, they are opposite in everything they do, except programming. Today they have a problem they cannot solve on their own, but together (with you) — who knows?
Every one of them has an integer sequences a and b of length n. Being given a query of the form of pair of integers (l, r), Mike can instantly tell the value of while !Mike can instantly tell the value of .
Now suppose a robot (you!) asks them all possible different queries of pairs of integers (l, r) (1 ≤ l ≤ r ≤ n) (so he will make exactly n(n + 1) / 2 queries) and counts how many times their answers coincide, thus for how many pairs is satisfied.
How many occasions will the robot count?
Input
The first line contains only integer n (1 ≤ n ≤ 200 000).
The second line contains n integer numbers a1, a2, ..., an ( - 109 ≤ ai ≤ 109) — the sequence a.
The third line contains n integer numbers b1, b2, ..., bn ( - 109 ≤ bi ≤ 109) — the sequence b.
Output
Print the only integer number — the number of occasions the robot will count, thus for how many pairs is satisfied.
Examples
Input
6
1 2 3 2 1 4
6 7 1 2 3 2
Output
2
Input
3
3 3 3
1 1 1
Output
0
Note
The occasions in the first sample case are:
1.l = 4,r = 4 since max{2} = min{2}.
2.l = 4,r = 5 since max{2, 1} = min{2, 3}.
There are no occasions in the second sample case since Mike will answer 3 to any query pair, but !Mike will always answer 1.
题目大意:
给你两个大小为n的数组a1,2,3,…n和b1,2,3,….n, 问你有多少个区间[l,r](1<=l<=r<=n), 使得max{al,al+1,al+2….,ar}和min{bl,bl+1,bl+2….,br}的值相等。
解题报告:
因为max随着区间的增加,具有单调不减的性质,min同理。所以我们可以枚举左端点,通过二分来确定右端点的一段合法区间。最后统计答案即可。
AC代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define FF first
#define SS second
#define ll long long
#define pb push_back
#define pm make_pair
using namespace std;
typedef pair<int,int> PII;
const int MAX = 2e5 + 5;
int n;
int a[MAX],b[MAX],Log[MAX];
int A[MAX][33],B[MAX][33];
void ST() {for(int i = 1; i<=n; i++) A[i][0] = a[i],B[i][0] = b[i];for(int j = 1; (1<<j)<=n; j++) {for(int i = 1; i+(1<<j)-1<=n; i++) {A[i][j] = max(A[i][j-1],A[i+(1<<j-1)][j-1]);B[i][j] = min(B[i][j-1],B[i+(1<<j-1)][j-1]);}}
}
int aMax(int l,int r) {int k = Log[r-l+1];return max(A[l][k],A[r-(1<<k)+1][k]);
}
int bMin(int l,int r) {int k = Log[r-l+1];return min(B[l][k],B[r-(1<<k)+1][k]);
}
int ans;
int main()
{for(int i = 2; i<MAX; i++) Log[i] = Log[i>>1] + 1;cin>>n;for(int i = 1; i<=n; i++) cin>>a[i];for(int i = 1; i<=n; i++) cin>>b[i];ST();for(int i = 1; i<=n; i++) {int l = i,r = n,mid,ans1=-1,ans2=0,Mx,Mn;while(l<=r) {mid = (l+r)>>1;Mx=aMax(i,mid),Mn=bMin(i,mid);if(Mx == Mn) ans1 = mid,l = mid+1;else if(Mx>Mn) r = mid-1;else l = mid+1; }l = i,r = ans1;while(l<=r) {mid = (l+r)>>1;if(aMax(i,mid) == bMin(i,mid)) ans2 = mid,r = mid-1;else l = mid+1;}ans += ans1-ans2+1;}cout << ans << endl;return 0 ;
}
甚至这题还可以用On的单调队列来写:
#include <bits/stdc++.h>
using namespace std;int n, a[200001], b[200001];
long long ans;
deque<int> mx, mn;
int main() {scanf("%d",&n);for(int i = 1; i <= n; i++) scanf("%d", &a[i]);for(int i = 1; i <= n; i++) scanf("%d", &b[i]);for(int i = 1, j = 1; i <= n; i++) {while(!mx.empty() and a[mx.back()] <= a[i]) mx.pop_back();while(!mn.empty() and b[mn.back()] >= b[i]) mn.pop_back();mx.push_back(i);mn.push_back(i);while(j <= i and a[mx.front()] - b[mn.front()] > 0) {j++;while(!mx.empty() and mx.front() < j) mx.pop_front();while(!mn.empty() and mn.front() < j) mn.pop_front();}if(!mx.empty() and !mn.empty() and a[mx.front()] == b[mn.front()]) ans += min(mx.front(), mn.front()) - j + 1;}printf("%lld", ans);
}
总结:
注意别直接这么写了:
for(int i = 1; i<=n; i++) {int l = i,r = n,mid,ans1=-1,ans2=0;while(l<=r) {mid = (l+r)>>1;if(aMax(i,mid) == bMin(i,mid)) ans1 = mid,l = mid+1;else r = mid-1; }l = i,r = ans1;while(l<=r) {mid = (l+r)>>1;if(aMax(i,mid) == bMin(i,mid)) ans2 = mid,r = mid-1;else l = mid+1;}ans += ans1-ans2+1;}
因为他不一定从i开始都是满足的,所以你求右端点的右边界的时候必须要分三种情况讨论。但是求左边界的时候就无所谓了。
不好理解的话可以画个图,假设一段区间的RMQ如图所示:(但是注意这不代表答案只是包含一段区间,因为可能有多段这样的图形出现。。。但是用单调队列还是没有问题的、注意维护值域的时候的判断条件)
枚举到以i为左端点时,我们要求的右端点的左右边界是l和r,所以二分的时候也要舍弃i~l这一段。