【例题】【观察范围】NKOJ3090 丢钉子

NKOJ3090 丢钉子
时间限制 : 20000 MS 空间限制 : 165536 KB

问题描述
学校里一年一度的自行车大赛又开始了!!可是ZL同学却非常不高兴,因为他不会骑自行车!所以他决定干扰这次比赛。他已经了解到了这次参加比赛的m名参赛选手的资料。他决定要进行一次惊天动地的干扰。
我们假设比赛场地是一个从起点处向右和向前无限延伸的跑道。编号为1到m的参赛队员从左到右并列排列。从比赛开始后的第1秒末,第2秒末,第3秒末,第4秒末……第m秒末他分别会投一枚钉子到当前排名第一的自行车的前面使其爆胎!(爆胎的自行车自动退出比赛,不再计入排名),当有多个人同时并列第一时,由于ZL童鞋在起点左侧的观众席,他总是丢在最接近左侧边缘的那个第一名参赛选手前(字典序最小的第一名)。
而参赛队员的资料只有两个,一个是他第一秒能前进的距离Vi,一个是他第一秒末后每秒秒能前进的距离Ai。
现在要你来求,每秒钟,ZL童鞋把钉子丢在了编号为几的参赛选手前。

输入格式
第一行为一个整数m,表示有m名参赛选手。
接下来有m行,分别表示编号为 i(从1到m)的参赛队员的数据,每行两个整数Vi,Ai。

输出格式
一行,m个整数,第i个数,表示第i秒退赛的选手的编号

样例输入
样例1
3
100 1
100 2
3 100

样例2
5
1 1
2 2
3 3
4 1
3 4

样例输出
样例1:
1 3 2
样例2:
4 5 3 2 1

提示
【样例1说明】
第一组测试数据
第1秒
选手1前进到100米处。
选手2前进到100米处。
选手3前进到 3 米处。
此时选手1、2并列第一,ZL把钉子丢在1号选手前,1号选手退出比赛。

第2秒
选手2前进到102米处。
选手3前进到103米处。
此时选手3第一。ZL把钉子丢在3号选手前,3号选手退出比赛。

第3秒
选手2前进到104米处。
此时选手2第一。ZL把钉子丢在2号选手前,2号选手退出比赛。

1 <= m <= 50000
0 <= Vi <= 500
0 < Ai <= 100

来源 hdu4393

观察500和100
结论一:因为速度只差大于等于1,所以500秒后顺序一定已经固定了->能A
结论二:相同速度的人们,第一秒的距离决定了他们出局的相对顺序,而速度最多只有100种->能A

#include<cstdio>
#include<iostream>
#include<queue>
#include<vector>
#include<algorithm>
using namespace std;
const int need=50004;

int m,maxv;
int v[need];

struct fy
{
    int dis,id;
    bool operator< (const fy &b) const
    {
        if(dis!=b.dis) return dis>b.dis;
        return id<b.id;
    }
} ;

vector<fy> w[102];
//................................
inline void in_(int &d)
{
    char t=getchar();
    while(t<'0'||t>'9') t=getchar();
    for(d=0;!(t<'0'||t>'9');t=getchar()) d=(d<<1)+(d<<3)+t-'0';
}
inline void out_(int x)
{
    if(x>=10) out_(x/10);
    putchar(x%10+'0');
}
//................................

int main()
{
    scanf("%d",&m);
    for(int i=1,a,b;i<=m;i++)
    {
        in_(a),in_(b);
        w[b].push_back((fy){a,i});
        maxv=max(maxv,b);
    }
    for(int i=1;i<=maxv;i++)
    {
        sort(w[i].begin(),w[i].end());
    }
    int tempdis,maxdis,ans,k;
    for(int i=0,j;i<m;i++)
    {
        maxdis=0;
        for(j=1;j<=maxv;j++)
        {
            if(!w[j].size()) continue;
            tempdis=w[j].begin()->dis+i*j;
            if(tempdis>maxdis)
            {
                maxdis=tempdis;
                ans=w[j].begin()->id;
                k=j;
            }
            else if(tempdis==maxdis&&ans>w[j].begin()->id) ans=w[j].begin()->id,k=j;
        }
        out_(ans),putchar(' ');
        w[k].erase(w[k].begin());
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值