题目大意
给定一个数列,求满足 mex ( a l ∼ a r ) > med ( a l ∼ a r ) \operatorname{mex}(a_l\sim a_r)>\operatorname{med}(a_l\sim a_r) mex(al∼ar)>med(al∼ar) 的区间 [ l , r ] [l,r] [l,r] 的个数。
解题思路
记 p i p_i pi 为 i i i 出现的位置。
我们可以枚举 d d d,先确定 mex ( a l ∼ a r ) > d \operatorname{mex}(a_l\sim a_r)>d mex(al∼ar)>d 的区间。由于数列是 0 ∼ n − 1 0\sim n-1 0∼n−1 的排列,所以这个区间必须包含 0 ∼ d 0\sim d 0∼d。用 l l l 记录区间最大左端点, r r r 记录区间最小左端点。可以在线维护 l , r l,r l,r,即 l = min { l , p d } , r = max { r , p d } l = \min\{l,p_d\},r = \max\{r,p_d\} l=min{l,pd},r=max{r,pd}。
接下来在考虑 med ( a l ∼ a r ) = d \operatorname{med}(a_l\sim a_r)=d med(al∼ar)=d。由于这个区间已经包含了 0 ∼ d 0\sim d 0∼d,所以长度就是 2 × d + 2 2\times d+2 2×d+2 和 2 × d + 1 2\times d+1 2×d+1。知道长度后,就可以 O ( 1 ) O(1) O(1) 统计答案了。
时间复杂度为 O ( n ) O(n) O(n),可以通过本题。
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
template <typename T> inline void read(T &x) {
x = 0; char ch = getchar(); int f = 1;
while (!isdigit(ch) && ch ^ '-') ch = getchar();
if (ch == '-') f = -1, ch = getchar();
while (isdigit(ch)) x = x * 10 + ch - 48, ch = getchar(); x *= f;
}
const int N = 1e7+5,mod = 41719;
int ans,n,a[N],l = N+1,r,p[N];
void work(int len)
{
if(r-l+1>len) return;
int _l = max(1ll,r-len+1),_r = min(l,n-len+1);
ans+=max(0ll,_r-_l+1);
}
signed main()
{
read(n);
for(int i = 1;i<=n;i++)
read(a[i]),p[a[i]] = i;
for(int i = 0;i<n;i++)
{
l = min(l,p[i]),r = max(r,p[i]);
int len = i*2+2;
work(len),work(len-1);
}
cout<<((n+1)*n/2-ans)%mod;
return 0;
}