2020杭电多校第一场I:Leading Robots

Problem Description
Sandy likes to play with robots. He is going to organize a running competition between his robots. And he is going to give some presents to the winners. Robots are arranged in a line. They have their initial position (distance from the start line) and acceleration speed. These values might be different. When the competition starts, all robots move to the right with speed: 


Here a is acceleration speed and t is time from starting moment.

Now, the problem is that, how many robots can be the leader from the starting moment?

Here leader means the unique rightmost robot from the start line at some moment. That is, at some specific time, if a robot is rightmost and unique then it is the leading robot at that time. There can be robots with same initial position and same acceleration speed.

The runway is so long that you can assume there's no finish line.
 
Input
The input consists of several test cases. The first line of input consists of an integer T(1≤ T≤50), indicating the number of test cases. The first line of each test case consists of an integer N(0 < N≤ 50000), indicating the number of robots. Each of the following N lines consist of two integers: p,a (0 < p,a < 231) indicating a robot's position and its acceleration speed.
 
Output
For each test case, output the number of possible leading robots on a separate line.
 
Sample Input
1 3 1 1 2 3 3 2
 
Sample Output
2

 题意:给定n个人一个初始位置和一个加速度,询问在很长一段时间内,共有多少人成为某一时刻唯一的第一名。

在时间t时,第i个人所处的位置为pi+(ai*t*t)/2.

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+9;
const double ep=1e-7;
const int mod=1e9+9;
#define mk make_pair
#define PII pair<int,int>
#define PLL pair<ll,ll>
#define pb push_back
typedef long long ll;
int sgn(double x)
{
    if(fabs(x)<ep)return 0;
    if(x>0)return 1;return -1;
}
struct point{
    ll a,p;
}p[maxn];
bool cmp(point a,point b)
{
    if(a.p==b.p)return a.a>b.a;
    return a.p>b.p;
}
vector<int>v;
int n;
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        p[n+1].a=p[n+1].p=0;
        for(int i=1;i<=n;i++)scanf("%d%d",&p[i].p,&p[i].a);
        sort(p+1,p+1+n,cmp);//最开始时的位置排序 
        //加速度最大的那个人肯定是最后的赢家 
        ll ma=p[1].a;
        stack<PII >s;//保存是第几个称为第一名 
        s.push(mk(1,1));
        for(int i=2;i<=n;i++)
        {
            if(p[i].a<=ma)continue;
            //如果加速度小于且本来位置比较靠后的话是不可能超过前面那个人的 
            ma=p[i].a;//根据最大加速度 
            int num=1;
            while(!s.empty())
            {
                PII pp=s.top();//前面i-1个人中是num1先超过了num2 
                int num1=pp.first;
                int num2=pp.second;
                double t2=sqrt(2.0*(p[i].p-p[num1].p)/(p[num1].a-p[i].a));
                double t1=0;
                if(num1!=num2)
                t1=sqrt(2.0*(p[num1].p-p[num2].p)/(p[num2].a-p[num1].a));
                if(sgn(t2-t1)<=0)
                {
                    num=num2;s.pop();
                    //说明在num1超过num2之前i就超过了num1
                    //说明i比num1先超过num2 
                }
                else
                {
                    num=num1;break;
                }
            }
            s.push(mk(i,num));
            //因为这个人的加速度最大,所以他在这前i个人中肯定是最后的赢家 
        } 
        int ans=s.size();
        while(!s.empty())
        {
            PII pp=s.top();s.pop();
            int num=pp.first;
            if(p[num].a==p[num+1].a&&p[num].p==p[num+1].p)ans--;
            //说明出现了不是唯一的情况 
        }
        printf("%d
",ans);
    }
}
欢迎加我qq1165750856一起玩呀~
原文地址:https://www.cnblogs.com/HHHEN/p/13392100.html