The Race
Description
During the Annual Interstellar Competition for Tuned Spaceships, N spaceships will be competing. Each spaceship i is tuned in such a way that it can accelerate in zero time to its maximum speed Vi and remain cruising at that speed. Due to past achievements, each spaceship starts at a starting position Xi, specifying how many kilometers the spaceship is away from the starting line.
The race course is infinitely long. Because of the high speeds of the spaceships, the race course goes straight all the time. On that straight course, spaceships can pass one another very easily, without interfering with each other.
Many people in the audience have not realized yet that the outcome of the race can be determined in advance. It is your task to show this to them, by telling them how many times spaceships will pass one another, and by predicting the first 10 000 times that spaceships pass in chronological order.
You may assume that each spaceship starts at a different position. Furthermore, there will never be more than two spaceships at the same position of the course at any time.
The race course is infinitely long. Because of the high speeds of the spaceships, the race course goes straight all the time. On that straight course, spaceships can pass one another very easily, without interfering with each other.
Many people in the audience have not realized yet that the outcome of the race can be determined in advance. It is your task to show this to them, by telling them how many times spaceships will pass one another, and by predicting the first 10 000 times that spaceships pass in chronological order.
You may assume that each spaceship starts at a different position. Furthermore, there will never be more than two spaceships at the same position of the course at any time.

Input
The first line of the input specifies the number of spaceshipsN (0 < N <= 250 000) that are competing. Each of the next N lines describe the properties of one spaceship. The i+1th line describes the ith ship with two integers Xi and Vi, representing the starting position and the velocity of the ith spaceship (0 <= Xi <= 1 000 000, 0 < Vi < 100). The spaceships are ordered according to the starting position, i.e. X1 < X2 < . . . < XN. The starting position is the number of kilometers past the starting line where the spaceship starts, and the velocity is given in kilometers per second.
Output
The first line of the output should contain the number of times that spaceships pass one another during the race modulo 1 000 000. By publishing the number of passes only modulo 1 000 000, you can at the same time prove your knowledge of it and don't spoil the party for the less intelligent people in the audience.
Each of the subsequent lines should represent one passing, in chronological order. If there would be more than 10 000 passings, only output the first 10 000 passings. If there are less than 10 000 passings, output all passings. Each line should consist of two integers i and j, specifying that spaceship i passes spaceship j. If multiple passings occur at the same time, they have to be sorted by their position on the course. This means that passings taking place closer to the starting line must be listed first. The time of a passing is the time when the two spaceships are at the same position.
Each of the subsequent lines should represent one passing, in chronological order. If there would be more than 10 000 passings, only output the first 10 000 passings. If there are less than 10 000 passings, output all passings. Each line should consist of two integers i and j, specifying that spaceship i passes spaceship j. If multiple passings occur at the same time, they have to be sorted by their position on the course. This means that passings taking place closer to the starting line must be listed first. The time of a passing is the time when the two spaceships are at the same position.
Sample Input
4
0 2
2 1
3 8
6 3
Sample Output
2
3 4
1 2
题意: 有n辆车, 在不同的位置上面, 每辆车有相应的速度, 现在要你求出超车时间的次数, 和每次超车的
两部车的编号.
解题思路:
1. 第一个问题就是逆序数问题, 速度的范围0~100不大, 可以用扫描的方法, 因为题目给出的汽车的,
顺序的从小编号到大编号, 当前第i 这部车的速度为v , 它可以被超车的数量num[v+1]+...+num[100];
2. 第二个问题, 我们假设, 对于任何时刻, 一个超车事件的发生, 必定是某辆车被离它最近的车辆超过,
我们就保存这样的一个时刻, 记录下当前车辆的id, 和要被超车的车辆id, 还有超车的时间需要多少,
超车之后当前车辆的位置. 此时问题可以解决, 每一个超车事件被我们记录在最小堆里面, 依次取出
需要时间最短输出即可.
3. 问题又来了, 当一辆车超过一辆车之后, 一辆车被一辆车超过之后, 会产生新的超车时间, 因为我们只
保存了两车相离最近的超车事件, 因此我们需要维护这个最小堆.
问题分析:
设4个变量 car_now //当前车的id
car_front //当前车的前面那辆车的id
car_back //当前车的后面那辆车的id
car_front_front //前面那辆车的前面那辆车的id
当一个超车事件发生, 这四部车的关系即发生关系, 如图:
4. 最后需要注意的是: 输出是有次数要求的, 还有一个是, 可能当前最小的超车事件可能不能用.
因为前一个超车时间改变了它.这个需要修正一下即可, 即是: 排除它不输出
代码:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <queue>
#include <vector>
using namespace std;
#define MAX 250005
#define MOD 1000000
struct node
{
double position, v;
}car[MAX];
struct node_pass
{
double time, position;
int id, front;
};
struct cmp
{
bool operator() (const node_pass &a, const node_pass &b)
{
if(a.time > b.time) return true; //时间短的先取
else if(b.time > a.time) return false;
else
{ //时间相同, 距离小的先取
if(a.position > b.position) return true;
else return false;
}
}
};
typedef priority_queue< node_pass, vector<node_pass>, cmp > pri_queue;
int n;
int num[105];
int back[MAX], front[MAX];
pri_queue qu;
long long result;
void read_data()
{
memset(front,-1,sizeof(front));
memset(back,-1,sizeof(back));
memset(num,0,sizeof(num));
result = 0;
for(int i = 0; i < n; ++i)
{
scanf("%lf %lf",&car[i].position, &car[i].v);
num[(int)car[i].v]++;
for(int j = (int)car[i].v+1; j <= 100; ++j)
result = (result + num[j]) % MOD;
}
//初始化前后车的关系
front[0] = 1;
back[n-1] = n-2;
for(int i = 1; i < n-1; ++i)
{
front[i] = i+1;
back[i] = i-1;
}
//将全部超车的事件放入最小堆里面
node_pass temp;
for(int i = 0; i < n-1; ++i)
{
if(car[i].v > car[i+1].v)
{
temp.time = (car[i+1].position-car[i].position) / (car[i].v-car[i+1].v);
temp.id = i;
temp.position = car[i].position + temp.time*car[i].v;
temp.front = i+1;
qu.push(temp);
}
}
}
void solve()
{
node_pass temp;
int car_now, car_front, car_back, car_front_front;
for(int i = 0; i < 10000 && !qu.empty(); ++i)
{
temp = qu.top();
qu.pop();
car_now = temp.id; //当前车的id
car_front = temp.front; //当前车的前面那辆车的id
car_back = back[temp.id]; //当前车的后面那辆车的id
car_front_front = front[car_front]; //前面那辆车的前面那辆车的id
//修正前后车的关系, 当发现关系变化之后不输出
if(back[car_front] != car_now || front[car_now] != car_front)
{
--i;
continue;
}
printf("%d %d\n",car_now+1, car_front+1);
//调整4部车的前后关系
if(car_back != -1) front[car_back] = car_front;
back[car_front] = car_back;
front[car_front] = car_now;
front[car_now] = car_front_front;
back[car_now] = car_front;
if(car_front_front != -1) back[car_front_front] = car_now;
if(car_back != -1 && car_front != -1)
{
if(car[car_back].v > car[car_front].v)
{
temp.id = car_back;
temp.time = (car[car_front].position-car[car_back].position) / (car[car_back].v-car[car_front].v);
temp.position = car[car_back].position + temp.time*car[car_back].v;
temp.front = car_front;
qu.push(temp);
}
}
if(car_front_front != -1 && car_now != -1)
{
if(car[car_now].v > car[car_front_front].v)
{
temp.id = car_now;
temp.time = (car[car_front_front].position-car[car_now].position) / (car[car_now].v-car[car_front_front].v);
temp.position = car[car_now].position + temp.time*car[car_now].v;
temp.front = car_front_front;
qu.push(temp);
}
}
}
}
int main()
{
//freopen("input.txt","r",stdin);
while(scanf("%d",&n) != EOF)
{
read_data();
printf("%lld\n",result);
solve();
}
return 0;
}