题目的大意是给出两个数组 ai,bi a i , b i ,判断有多少个区间 [l,r] [ l , r ] ,使得数组a在这个区间中的最大值,等于数组B在区间中的最小值
首先不对数组进行操作我们可以用ST表来实现取最值的操作。其次,我们要知道假设固定区间的左端点,最大值是非降的,最小值是非升的,那么有了线性的性质我们就可以二分了。
我们每次固定一个左端点,找出让 MAX∑ni=1ai=MIN∑ni=1bi M A X ∑ i = 1 n a i = M I N ∑ i = 1 n b i 的最大位置和最小位置,答案加上这个区间的长度即可。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#include <map>
#include <cmath>
#include <iostream>
#define ll long long
#define x first
#define y second
using namespace std;
const int MAXN = 2e5+10;
int da[MAXN][20];
int db[MAXN][20];
int ma[MAXN];
int mb[MAXN];
int A[MAXN],B[MAXN];
void initRMQMAX(int n,int b[])
{
ma[0] = -1;
for(int i = 1; i <= n; i++)
{
ma[i] = ((i&(i-1)) == 0)?ma[i-1]+1:ma[i-1];
da[i][0] = b[i];
}
for(int j = 1; j <= ma[n]; j++)
for(int i = 1; i + (1<<j) -1 <= n; i++)
da[i][j] = max(da[i][j-1],da[i+(1<<(j-1))][j-1]);
}
void initRMQMIN(int n,int b[])
{
mb[0] = -1;
for(int i = 1; i <= n; i++)
{
mb[i] = ((i&(i-1)) == 0)?mb[i-1]+1:mb[i-1];
db[i][0] = b[i];
}
for(int j = 1; j <= mb[n]; j++)
for(int i = 1; i + (1<<j) -1 <= n; i++)
db[i][j] = min(db[i][j-1],db[i+(1<<(j-1))][j-1]);
}
//查询最大值
int amax(int x,int y)
{
int k = ma[y-x+1];
// cout<<"check max on:"<<x<<" "<<y<<"get "<<max(da[x][k],da[y-(1<<k)+1][k])<<endl;
return max(da[x][k],da[y-(1<<k)+1][k]);
}
int bmin(int x,int y)
{
int k = mb[y - x+1];
//cout<<"check min on:"<<x<<" "<<y<<"get "<<min(db[x][k],db[y-(1<<k) +1][k])<<endl;
return min(db[x][k],db[y-(1<<k) +1][k]);
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int n;
cin>>n;
for(int i = 1;i<=n;i++)
{
cin>>A[i];
}
initRMQMAX(n,A);
for(int i = 1;i<=n;i++)
{
cin>>B[i];
}
initRMQMIN(n,B);
ll ans = 0;
for(int i = 1;i<=n;i++)
{
int l = i;
int r = n;
int st = -1;
while(l <= r)
{
int mid = (l +r)/2;
int aa = amax(i,mid);
int bb = bmin(i,mid);
if(aa >= bb)
{
if(aa == bb) st = mid;
r = mid-1;
}
else
{
l = mid+1;
}
}
if(st == -1) continue;
l = i,r = n;
int en = -1;
while(l <= r)
{
int mid = (l + r) /2;
int aa = amax(i,mid);
int bb = bmin(i,mid);
if(aa > bb) r = mid-1;
else
{
if(aa == bb) en = mid;
l = mid+1;
}
}
if(en == -1) continue;
ans += (en - st +1);
}
cout<<ans<<endl;
return 0;
}