解题思路:本题转换一下描述就是把这个数组的每一个值(去重)从小到大排列,然后依次把它们所在的位置按顺序都变成0(变成0就不再变回来),求再变化的过程中非零段个数最大是多少。由于本题数据量很大,所以要采取优化,在于每次的变化都要在上一次的变化当中去找,本次变化对上一次的结果有何影响(不然只有70分)。
#include<bits/stdc++.h>
#define MAX 500001
using namespace std;
using gg = long long;
vector<int> arr(MAX);
map<int,vector<int> > mp;
gg n;
gg res = 0;
gg max_len = 0;
void fun(gg left,gg right)
{
if(left>0&&right<n-1)//左有右有
{
if(arr[left-1]==0&&arr[right+1]==0)
{
res-=1;
}
else if(arr[left-1]!=0&&arr[right+1]!=0)
{
res+=1;
}
}
else if(left==0&&right<n-1)//左无右有
{
if(arr[right+1]==0) res-=1;
}
else if(left>0&&right==n-1)//左有右无
{
if(arr[left-1]==0) res-=1;
}
else if(left==0&&right==n-1)//左无右无
{
res-=1;
}
}
int main()
{
std::ios::sync_with_stdio(false);
cin.tie(nullptr);
cin>>n;
for(gg i=0;i<n;i++)
{
cin>>arr[i];
if(i>0&&arr[i]==0&&arr[i-1]!=0)
{
res+=1;
}
if(arr[i]!=0)
{
mp[arr[i]].push_back(i);
}
}
if(arr[n-1]!=0) res+=1;
max_len=res;
for(map<int,vector<int> >::iterator it =mp.begin();it!=mp.end();it++)
{
//cout<<1<<endl;
vector<int> cur = it->second;
int size = cur.size();
for(gg j=0;j<size;j++)
{
gg k;
gg left = cur[j];
gg right = cur[j];
for(k=j+1;k<size;k++)
{
if(cur[k]==right+1)
{
right=cur[k];
}
else
{
break;
}
}
j = k-1;
fun(left,right);
}
max_len=max(res,max_len);
for(gg p=0;p<size;p++)
{
arr[cur[p]]=0;
}
}
cout<<max_len<<endl;
return 0;
}