【黑暗爆炸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;
}