首先,我在机房用了五台电脑进行对拍。数据生成器:
#include<bits/stdc++.h>
using namespace std;
int n;
mt19937 rnd(chrono::system_clock::now().time_since_epoch().count());
signed main(){
freopen("I.in","w",stdout);
n=rnd()%10000+80000;
cout<<n<<'\n';
for(int i=1;i<=n;i++){
cout<<rnd()%20+1<<' ';
}
return 0;
}
然而他们现在都没有拍出来,令我气愤。
我的思路是求出“区间”,“区间”开头就是自己的下标,末尾就是下一个和自己数字相同的值的下标。
如图所示:

用橙色线连的就是“区间”(实际上就只有那两个数)。
然后对终点进行排序,从小到大。
再记录一个 maxn,代表当前最大的终点的下标。
下一个区间的开始必须大于当前的 maxn。
如图所示:
(依次用、红、橙、黄、绿、蓝、深蓝,来代表下一次操作,粉色代表当前 ans)

这是代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2e5 + 1;
int a[N], n, ans, frt[N];
bool b[N];
struct Node {
int from, v;
} nxt[N];
signed main() {
// freopen("I.in","r",stdin);
// freopen("wrong.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0);
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
frt[a[i]] = 0x3f3f3f3f;
}
for (int i = n; i >= 1; i--) {//frt 记录区间终点
nxt[i].v = frt[a[i]];
nxt[i].from = i;
frt[a[i]] = i;
}
sort(nxt + 1, nxt + 1 + n, [](Node x, Node y) {return x.v < y.v;});//通过区间最后一个点排序
int maxn = 0;
for (int i = 1; i <= n; i++) {
if (nxt[i].v == 0x3f3f3f3f)break;//如果后面没了就 break
if (nxt[i].from > maxn && !b[a[nxt[i].from]]) {//起点必须大于当前终点最大值
ans += 2;//当前这个点和终点共两个
b[a[nxt[i].from]] = 1;//记录这个值用过
maxn = nxt[i].v;
}
}
cout << ans;
return 0;
}
求 hack 数据。