【黑暗爆炸2457】双端队列

双端队列

——黑暗爆炸2457

题目传送门

https://vjudge.net/contest/406355#problem/B

思路

我们理解一下题意,就可以转换为在一个有序数列中找出最小个数的双端队列。观察可得双端队列都满足先单调递减再单调递增的特性。因此我们可以想到:将数据按照大小和下标进行非降序排序,扫一遍排序后的数组,计算拐点(先降再升的点)。时间复杂度O(n)

代码实现

#include <bits/stdc++.h>
#define ll long long
#define ull unsigned long long
using namespace std;
inline int read(){
	int f = 0,num;
	char ch;
	while(ch = getchar(),!isdigit(ch))if(ch == '-')f = 1;num = ch-'0';
	while(ch = getchar(), isdigit(ch))num = num * 10 + ch - '0';
	return f?-num:num;
}
const int N = 2e5+3;
int n;
struct node{
	int id;
	int num;
}s[N];
bool cmp(node a,node b){
	if(a.num == b.num) return a.id < b.id;
	return a.num < b.num;
}
int main(){
	n = read();
	for(int i = 1; i <= n; i++){
		s[i].num = read();
		s[i].id = i;
	}
	sort(s + 1,s + 1 + n,cmp);
	int f=1,ans=1;
	int tmp=2e9;
	int i=1;
	while(i<=n)
	{
        int j = i;
        while (s[j + 1].num == s[j].num && j < n) 
			j++;
        if (f == 1) 
		{
            if(s[j].id < tmp) tmp = s[i].id;
            else 
			{
                f = 0;
                tmp = s[j].id;
            }
            
        } 
		else
		{
            if(s[i].id > tmp) tmp = s[j].id;
            else
			{
                f = 1;
                ans++;
                tmp = s[i].id;
            }
        }
        i = j + 1;
    }
    printf("%d",ans);
	return 0;
}
posted @ 2020-11-25 10:36  Shayndel  阅读(102)  评论(0编辑  收藏  举报