【题解】P11187 配对序列
P11187 配对序列
小学生都会做的小清新递推题。
我们不妨定义:
- 一个“完整配对子序列”为题目所述的配对子序列
- 一个“不完整配对子序列”为题目所述配对子序列去掉末尾的数
可以发现:
-
一个“完整配对子序列”加上一个不等于其末尾的数就是一个“不完整配对子序列”。
-
一个“不完整配对子序列”加上一个等于其末尾的数就是一个“完整配对子序列”。
考虑维护在 到 中以 为结尾的最长“完整配对子序列”和“不完整配对子序列”的长度。
- 对于“完整配对子序列”,直接用 中的以 为结尾的“不完整配对子序列”的长度加一更新即可。
- 对于“不完整配对子序列”,需要求出 中结尾不等于 的“完整配对子序列”的长度的最大值。考虑将所有的“完整配对子序列”的长度的最大值插入一个数据结构,把结尾等于 的最大值删除,最后求最大值即可。
因此我们需要一个可以快速动态插入、删除、求最大值的数据结构,使用 multiset 即可。注意 multiset 要删除单个某个数不能直接删除,得先 find 到这个数,再删除 find 出来的迭代器。
#include <iostream>
#include <iomanip>
#include <cmath>
#include <string>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <set>
#define int long long
#define endl '\n'
#define IL inline
using namespace std;
const int N = 5e5 + 10;
const int INF = 0x3f3f3f3f;
IL int read()
{
int x = 0,f = 1;
char c = getchar();
while(c <'0'|| c >'9'){if(c == '-') f = -1;c = getchar();}
while(c >= '0' && c <= '9') x = x * 10 + c - '0',c = getchar();
return x * f;
}
void write(int x)
{
if(x > 9) write(x / 10);
putchar(x % 10 + '0');
}
int n, a[N];
int ans, com[N], inc[N];
multiset <int> st;
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n;
for(int i = 1;i <= n;i++) cin >> a[i];
for(int i = 1;i <= n;i++)
{
//维护完整子序列
if(inc[a[i]])
{
if(st.find(com[a[i]]) != st.end()) st.erase(st.find(com[a[i]]));
com[a[i]] = max(com[a[i]], inc[a[i]] + 1);
st.insert(com[a[i]]);
}
//维护不完整子序列
if(st.find(com[a[i]]) != st.end()) st.erase(st.find(com[a[i]]));
if(st.size()) inc[a[i]] = max(inc[a[i]], (*st.rbegin()) + 1ll);
else inc[a[i]] = max(inc[a[i]], 1ll);
st.insert(com[a[i]]);
ans = max(ans, *st.rbegin());
}
cout << ans << endl;
return 0;
}

浙公网安备 33010602011771号