CF1744F MEX vs MED 題解

pyy1發表於2024-04-08

題目傳送門

題目大意

給定一個數列,求滿足 \(\operatorname{mex}(a_l\sim a_r)>\operatorname{med}(a_l\sim a_r)\) 的區間 \([l,r]\) 的個數。

解題思路

\(p_i\)\(i\) 出現的位置。

我們可以列舉 \(d\),先確定 \(\operatorname{mex}(a_l\sim a_r)>d\) 的區間。由於數列是 \(0\sim n-1\) 的排列,所以這個區間必須包含 \(0\sim d\)。用 \(l\) 記錄區間最大左端點,\(r\) 記錄區間最小左端點。可以線上維護 \(l,r\),即 \(l = \min\{l,p_d\},r = \max\{r,p_d\}\)

接下來在考慮 \(\operatorname{med}(a_l\sim a_r)=d\)。由於這個區間已經包含了 \(0\sim d\),所以長度就是 \(2\times d+2\)\(2\times d+1\)。知道長度後,就可以 \(O(1)\) 統計答案了。

時間複雜度為 \(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;
}

相關文章