G.ACM is all you need
分析:
-
map 遍历,分类讨论,思维
-
若对 a [ i ] ( 1 < i < n ) a[i](1<i<n) a[i](1<i<n) 展开讨论,会有四种情况
- a [ i ] < a [ i + 1 ] a n d a [ i ] < a [ i − 1 ] a[i]<a[i+1] \ and\ a[i]<a[i-1] a[i]<a[i+1] and a[i]<a[i−1]:会对 ans 贡献1,当b比某个值还要大时,会对 ans 贡献-1
- a [ i ] > a [ i + 1 ] a n d a [ i ] > a [ i − 1 ] a[i]>a[i+1] \ and\ a[i]>a[i-1] a[i]>a[i+1] and a[i]>a[i−1]:当b大于某个值时,会对 ans 贡献1
- a [ i ] > a [ i + 1 ] a n d a [ i ] < a [ i − 1 ] a[i]>a[i+1] \ and\ a[i]<a[i-1] a[i]>a[i+1] and a[i]<a[i−1]:当b大于某个值会对 ans 贡献1,再大一些,大于第二个值时,会贡献-1
- a [ i ] < a [ i + 1 ] a n d a [ i ] > a [ i − 1 ] a[i]<a[i+1] \ and\ a[i]>a[i-1] a[i]<a[i+1] and a[i]>a[i−1]:同(3)
-
最后的贡献,就是“某个值”从小到大,贡献值的前缀和
-
每种情况的“某个值”,可以通过画图或举例来求出具体如何表示
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int a[N];
void solve()
{
int n;
cin>>n;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
int ans=0;
map <int,int> mp;
for(int i=2;i<n;i++)
{
if(a[i]<a[i+1] && a[i]<a[i-1])
{
ans++;
int mn=min(a[i-1],a[i+1]);
mp[(a[i]+mn+1)/2]++;
}
else if(a[i]>a[i+1] && a[i]>a[i-1])
{
int mx=max(a[i+1],a[i-1]);
mp[(a[i]+mx)/2+1]--;
}
else if(a[i]>a[i+1] && a[i]<a[i-1])
{
mp[(a[i]+a[i+1])/2+1]--;
mp[(a[i]+a[i-1]+1)/2]++;
}
else if(a[i]>a[i-1] && a[i]<a[i+1])
{
mp[(a[i]+a[i-1])/2+1]--;
mp[(a[i]+a[i+1]+1)/2]++;
}
}
int now=0,mx=0;
for(auto it : mp)//遍历
{
now+=it.second;
mx=max(now,mx);
}
cout<<ans-mx<<endl;
}
signed main()
{
int t=1;
cin>>t;
while(t--) solve();
}