http://acm.hdu.edu.cn/showproblem.php?pid=6759
题意:是说给你很多个初始位置和加速度的机器人.然后问你有多少个机器人曾经拿过rk1,并列不算.
怎么写呢?首先我们应该知道,假如两条线重合.那么显然是不能作为答案的,我们要标记一下.对于每个机器人来说他们的运动轨迹都可以看成是一条一次函数.然后我们就可以发现很多性质了,解方程的性质.
画个图:
图片说明
我们很容易发现,假如我们先拿起始坐标按p排序,维护一个栈,就可以作为答案,首先我们把第一条线的信息放入栈,然后假如a小于栈顶里面的a那么显然不可能成为rk1,因为你起点低,后劲少怎么可能当rk1(好像说的就是我.)假如a大于栈顶那么就有机会当rk1了,这时候我们需要判断一下了,判断什么呢?忘记说了,我们的栈是维护的一个当rk1最先时间的单调栈.判断就是看谁当rk1的时间更快,具体怎么看呢?没错就是看交点,假设当前栈头为top,那么它后面一个就是top-1,假设我当前的匹配到了第i条线,假如说i和top-1的交点的时间比top和top-1交点的时间要短,显然top是不可能成为rk1的.
图片说明
代码如下:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e4+5;
struct vv{
    ll p,a;//起始坐标 加速度.
}v[N];

bool cmp(vv x,vv y)//优先p然后a
{
    if(x.p==y.p)    return x.a>y.a;
    else            return x.p>y.p;
}
stack<int>s;//定义rk1时间的单调栈
int mp[N];//标记那些没有价值的线段
int main()
{
    ll t,n,ans=0;
    while(scanf("%lld",&t)!=EOF)
    {
        while(t--)
        {
            ans=0;
            memset(mp,0,sizeof mp);
            scanf("%lld",&n);
            for(ll i=1;i<=n;i++)
            {
                scanf("%lld%lld",&v[i].p,&v[i].a);
            }//输入
            sort(v+1,v+1+n,cmp);//排序
            for(ll i=1;i<=n;i++)
            {
                if(v[i].p==v[i-1].p&&v[i].a==v[i-1].a)
                {
                    mp[i]=1;mp[i-1]=1;
                }
            }
            s.push(1);
            for(int i=2;i<=n;i++)
            {
                if(v[i].a<=v[s.top()].a) continue;
                while(s.size()>1)
                {
                    int temp=s.top();
                    s.pop();
                    int last=s.top();
                    double ti=(double)(v[i].p-v[last].p)/(double)(v[last].a-v[i].a);
                    double ts=(double)(v[temp].p-v[last].p)/(double)(v[last].a-v[temp].a);
                    if(ti>ts)
                    {
                        s.push(temp);
                        s.push(i);
                        break;
                    }
                }
                if(s.size()==1) {s.push(i);}
            }
            while(s.size())
            {
                if(!mp[s.top()]) ans++;
                s.pop();
            }
            printf("%lld\n",ans);
        }
    }
    return 0;
}