2020杭电多校第一场1009 Leading Robots 6759 (单调栈)
题目
http://acm.hdu.edu.cn/showproblem.php?pid=6759
题意
给了n个机器人的初始位置p和加速度a,起始速度都是0,问起跑后,问你有多少个机器人当过第一名,即在某一时刻,有唯一一个机器人如果冲在最前面则他是当过第一名的,注意并列第一则不算第一,赛道是无限长的。
题解
可以利用单调栈去储存当过第一的机器人。
先把机器人按照位置最远(位置相同按照加速度大在前面,加速度小的放前面会wa)排序。
然后遍历,只要能超过栈顶元素就可以放到栈中,但是如果还能超越栈顶后面的元素,那么栈顶的这个元素就pop掉(因为他不可能领头)。
然后用map去记录栈里面元素p和a出现的次数,如果有一个以上p和a相同的,说明存在并排的机器人,不能算进答案。
AC代码
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
using namespace std;
#define ll long long
#define INF 999999999
#define mem(a,b) memset(a,b,sizeof(a))
#define PI acos(-1)
const int maxn = 5e5+5;
const ll mod = 1e9+7;
const double eps = 1e-6L;
struct node
{
ll local,a;
double tim;
} car[maxn],s[maxn];
bool cmp(node x,node y)
{
if(x.local!=y.local)
return x.local>y.local;
return x.a>y.a;
}
double cal(node x,node y)
{
if(y.a!=x.a)
return 1.0*(x.local-y.local)/(y.a - x.a);
else if(x.local==y.local) return 0;
else return INF;
}
int dcmp(double a,double b){
if(-eps<=max(a,b)-min(a,b)&&max(a,b)-min(a,b)<=eps)return 0;
if(a<b)return -1;
else
return 1;
}
int main()
{
// freopen("1.txt","r",stdin);
// freopen("ans.txt","w",stdout);
int T;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
for(int i=0; i<n; i++)
{
scanf("%lld %lld",&car[i].local,&car[i].a);
}
sort(car,car+n,cmp);
map<pair<ll,ll>,int> mp;
mp.clear();
stack<node> s;
car[0].tim = INF;
s.push(car[0]);
mp[{car[0].local,car[0].a}]++;
for(int i = 1; i<n;i++)
{
node x;
x = s.top();
if(car[i].a<x.a)
continue;
if(car[i].a==x.a&&car[i].local!=x.local)
continue;
double res = cal(x,car[i]);
while(s.size()>1&&dcmp(res,x.tim)<=0)
{
s.pop();
x = s.top();
res = cal(x,car[i]);
}
car[i].tim = res;
x = car[i];
s.push(x);
mp[{car[i].local,car[i].a}]++;
}
int ans=0;
while(!s.empty())
{
node x = s.top();
s.pop();
if(mp[{x.local,x.a}] == 1)
{
ans++;
}
}
printf("%d\n",ans);
}
return 0;
}
/*
1
10
2560 1
2483 154
2252 308
1867 462
1328 616
635 770
2564 67
2564 15
2567 38
2570 19
*/