[BZOJ2457] [BeiJing2011] 双端队列 [贪心][构造]

[ L i n k \frak{Link} ]


考虑到一个双端队列,先放的是中间某一个权值,
然后往左添加的数权值单调不递增,往右添加的数权值单调不递减。
容易发现往左添加、往右添加都一定要比一开始添加的晚,而且越靠近两端越晚。
考虑按照权值排序,显然只有位置↘↗的区间会被选到最后的双端队列里
在实现的时候对相同数的处理比较麻烦。
不过其实也还好,相邻相同缩点就行了。


#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<cctype>
using namespace std;
int n, t, ans, m, tail = 0x3f3f3f3f;
bool cond;
pair<int, int> a[200005];
int Mx[200005];
int Mn[200005];
int main() {
	scanf("%d", &n);
	for (int i = 1; i <= n; ++i) {
		scanf("%d", &t);
		a[i] = make_pair(t,i);
	}
	sort(a+1, a+1+n);
	Mn[++m] = a[1].second;
	for (int i = 2; i <= n; ++i) {
		if (a[i].first == a[i-1].first) continue;
		Mx[m] = a[i-1].second;
		Mn[++m] = a[i].second;
	} Mx[m] = a[n].second;
	for (int i = 1; i <= m; ++i) {
		if (cond) {
			if (tail > Mx[i]) tail = Mn[i];
			else tail = Mx[i], cond = 0;
		} else {
			if (tail < Mn[i]) tail = Mx[i];
			else tail = Mn[i], cond = 1, ++ans;
		}
	}
	printf("%d", ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Estia_/article/details/83865993