题目描述
小 W 准备参加 IOSJ,但 IOSJ 作为一个选拔性质的比赛会进行很多轮,在每轮之后每位 选手的得分都会发生变化,小 W 想研究这些选手排名的变化情况。 IOSJ 共有 N 位选手,编号依次为[1,N]。第 i 位选手在第一轮结束后的得分为 a[i]。现在小 W 收集到了第二轮的得分情况,第 i 位选手每秒会增加 b[i]分,你可以认为第二轮的时间为无限长。 定义一次排名的“追赶”如下:(1)在某个时刻 x 秒之前(x 可以为小数),编号为 a 的选手分数小于编号为 b 的选手;(2)在时刻 x 秒的时候,编号为 a,b 的两位选手分数相同。 满足以上两点的事件称为“追赶”。现在小 W 想让你求出按照时间排序后前 M 次“追赶”时的编号 a 和编号 b(时间相同追赶者的编号更小的优先,时间和追赶者编号都相同时被追赶者编号更小的优先)。
输入输出格式
输入格式:
第一行一个整数 N,表示选手总数。 接下来 N 行,第 i+1 行两个整数表示 a[i],b[i]。 接下来一行一个整数 M。
输出格式:
共 M 行,第 i 行两个整数分别表示第 i 次追赶的追赶者和被追赶者。
输入输出样例
输入样例#1: 复制
2 1 100 3 1 1
输出样例#1: 复制
1 2
输入样例#2: 复制
4 4 2 2 9 9 2 5 6 3
输出样例#2: 复制
2 1 2 3 2 4
说明
对于 10%的数据,满足 N<=500。 对于 30%的数据,满足 N<=10000。 对于 50%的数据,满足 N<=100000,M<=1000。 对于另外 20%的数据,满足 N<=10000,M<=20000。 对于 100%的数据,满足 N,M<=100000,1<=a[i],b[i]<=1000000000,保证存在至少 M 次 追赶,且所有 a[i]互不相同。保证第 M 次和第 M+1 次追赶的时间不相同。
使用链表维护所有人的相对位置,那么一个人超过另一个人的时候只要把链表中两个相邻的
数进行交换。在维护链表的同时把每一组相邻的人的超越时间放到一个堆中,那么下一次的
超越就是堆顶的事件。
#include<bits/stdc++.h>
#define f(i,l,r) for(i=(l);i<=(r);i++)
using namespace std;
const int MAXN=100005,MOD=10000019;
double EPS=1e-9;
struct Node{
int a,b,id;
bool operator < (const Node& tmp)const{
return a<tmp.a;
}
}e[MAXN];
struct Event{
int u,v;
bool operator < (const Event& tmp)const{
double tim1=1.0*(e[v].a-e[u].a)/(e[u].b-e[v].b);
double tim2=1.0*(e[tmp.v].a-e[tmp.u].a)/(e[tmp.u].b-e[tmp.v].b);
if(fabs(tim1-tim2)<EPS){
if(e[u].id==e[tmp.u].id) return e[v].id<e[tmp.v].id;
return e[u].id<e[tmp.u].id;
}
return tim1<tim2;
}
};
set<Event> q,p;
int n,m;
int l[MAXN],r[MAXN];
void Swap(int x,int y)
{
r[l[x]]=y;
l[y]=l[x];
l[x]=y;
r[x]=r[y];
l[r[y]]=x;
r[y]=x;
}
int main()
{
ios::sync_with_stdio(false);
int i,j;
cin>>n;
f(i,1,n){
cin>>e[i].a>>e[i].b;
e[i].id=i;
}
cin>>m;
sort(e+1,e+1+n);
f(i,1,n){
l[i]=i-1;
r[i]=i+1;
}
f(i,1,n-1){
if(e[i].b<=e[i+1].b) continue;
double tim=1.0*(e[i+1].a-e[i].a)/(e[i].b-e[i+1].b);
q.insert((Event){i,i+1});
}
f(i,1,m){
set<Event>::iterator it=q.begin();
q.erase(it);
Event cur=*it;
p.insert(cur);
if(l[cur.u]){
if(e[l[cur.u]].b>e[cur.v].b){
// double tim=1.0*(e[cur.v].a-e[l[cur.u]].a)/(e[l[cur.u]].b-e[cur.v].b);
q.insert((Event){l[cur.u],cur.v});
}
}
if(r[cur.v]<=n){
if(e[cur.u].b>e[r[cur.v]].b){
q.insert((Event){cur.u,r[cur.v]});
}
}
Swap(cur.u,cur.v);
}
f(i,1,m){
set<Event>::iterator it=p.begin();
p.erase(it);
Event cur=*it;
cout<<e[cur.u].id<<" "<<e[cur.v].id<<endl;
}
return 0;
}