1. 程式人生 > 實用技巧 >2020 Multi-University Training Contest 1 1009 Leading Robots

2020 Multi-University Training Contest 1 1009 Leading Robots

題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=6759

題意:給你n個機器人離起跑線的距離p和加速度a,開始起跑後,問你有多少個機器人當過第一名,即在某一時刻,

其他機器人都在這個機器人的後面,則在此時刻該機器人是第一名,賽道是無限長的。

思路:所以機器人先按加速度a從大到小排序,加速度相同則按離起跑線的距離p從大到小排序,如果某個機器人的加速度a和距離p都小於或等於另一個機器人,那這個機器人是不可 能排到第一的。然後剛開始的第一名是距離最大的那個機器人,然後再按加速度從小到大遍歷機器人,用一個棧存取可能為第一名的機器人,如果棧中的機器人小於2個,就直接加入,否則如果第i個機器人超過棧中第2個機器人的時間小於或等於棧中第一個機器人超過棧中第2個機器人的時間,那棧中第一個機器人也不可能成為第一名,可以直接去掉,然後再把第i個機器人加入棧中即可。由於並列第一不算第一名,所以最後棧中的某個機器人的a和p和另一個機器人的a和p一樣的話就要不掉,可以用map記錄。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
struct node
{
    ll p;
    ll a;
}a[50005],b[50005],c[50005];
bool cmp(node x,node y)
{
    if(x.a==y.a)
        return x.p>y.p;
    else
        return x.a>y.a;
}
double fun(node x,node y)//返回的是機器人x超過y的時間的平方
{
    double ans=2*(y.p-x.p);
    ans=ans/(x.a-y.a)*1.0;
    return ans;
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        map<ll,map<ll,ll> >mp;
        int n;
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            cin>>a[i].p>>a[i].a;
            mp[a[i].p][a[i].a]++;
        }
        sort(a+1,a+n+1,cmp);
        int h=1;
        b[h]=a[1];
        ll ma=a[1].p;
        for(int i=2;i<=n;i++)
        {
            if(a[i].p>ma)
            {
                ma=a[i].p;
                b[++h]=a[i];
            }
        }
        int k=1;
        c[1]=b[h];
        for(int i=h-1;i>=1;i--)
        {
            if(k<=1)
            {
                c[++k]=b[i];
                continue;
            }
            while(k>=2)
            {
                if(fun(b[i],c[k])<=fun(c[k],c[k-1]))
                    k--;
                else
                    break;
            }
            c[++k]=b[i];
        }
        int ans=0;
        for(int i=1;i<=k;i++)
        {
            if(mp[c[i].p][c[i].a]==1)
                ans++;
        }
        cout<<ans<<endl;
    }
}