BZOJ 4391: [Usaco2015 dec]High Card Low Card

预处理一下前缀后缀最大值
每次用set贪心取一个合适的数
然后枚举分割点
有可能两次都取了同一个数 \(x\),而 \(y\) 没被取到
\(x>y\),那么就可以在点数小的那一轮拿 \(y\) 替换 \(x\)
\(x<y\),那么就可以在点数大的那一轮拿 \(y\) 替换 \(x\)

#include <bits/stdc++.h>

inline int _i() {
	int x = 0, f = 1; char ch = getchar();
	while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
	while (ch >= '0' && ch <= '9') x = x * 10 + ch - 48LL, ch = getchar();
	return x * f;
}

const int N = 1e5 + 7;
int a[N], pre[N], suf[N];
bool vis[N];
std::set<int> st;

int main() {
	int n = _i();
	for (int i = 1; i <= n; i++)
		vis[a[i] = _i()] = 1;
	for (int i = 1; i <= 2 * n; i++)
		if (!vis[i]) st.insert(i);
	std::set<int>::iterator it;
	for (int i = 1; i <= n; i++) {
		it = st.lower_bound(a[i]);
		pre[i] = pre[i - 1];
		if (it != st.end()) st.erase(it), pre[i]++;
	}
	st.clear();
	for (int i = 1; i <= 2 * n; i++)
		if (!vis[i]) st.insert(i);
	for (int i = n; i; i--) {
		it = st.lower_bound(a[i]);
		suf[i] = suf[i + 1];
		if (it != st.begin()) --it, st.erase(it), suf[i]++;
	}
	int ans = 0;
	for (int i = 0; i <= n; i++)
		ans = std::max(ans, pre[i] + suf[i + 1]);
	printf("%d\n", ans);
	return 0;
}
posted @ 2020-02-18 09:09  Mrzdtz220  阅读(87)  评论(0)    收藏  举报