[CF1479B2/CF1480D2] Painting the Array II
Description
将一个序列拆成两个子序列,然后每个子序列中相邻相同的元素只保留一个,最小化剩下元素的个数。
Solution
贪心,决定每个元素 \(a[i]\) 放在哪里,需要考虑 \(a[i]\),下个和 \(a[i]\) 相等的数的位置,以及当前已有子序列的末尾
每个元素进来的时候,如果不能直接接在一个相同的末尾后面的话,必然要毁掉一个当前的末尾延续到下一个相同元素的可能
设 A 队队尾的下个元素位置为 pA,B 队为 pB
如果 pA 小于 pB,意味着 B 队尾在今后遭遇危险的可能性更大,因此我们选择 B 插入,反之亦然
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 100005;
int n,a[N];
vector <int> g[N];
int nxt[N];
signed main()
{
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i], g[a[i]].push_back(i);
for(int i=1;i<=n;i++) nxt[i]=n+1;
for(int i=1;i<=n;i++) for(int j=1;j<g[i].size();j++) nxt[g[i][j-1]]=g[i][j];
int val1=0,nxt1=n+1,val2=0,nxt2=n+1;
int ans=0;
for(int i=1;i<=n;i++)
{
int val=a[i];
if(val==val1) nxt1=nxt[i];
else if(val==val2) nxt2=nxt[i];
else
{
if(nxt1>nxt2)
{
val1=val;
nxt1=nxt[i];
++ans;
}
else
{
val2=val;
nxt2=nxt[i];
++ans;
}
}
}
cout<<ans<<endl;
}