The Race
Time Limit: 15000MS | Memory Limit: 65536K | |
Total Submissions: 3237 | Accepted: 664 | |
Case Time Limit: 3000MS |
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.
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.
Sample Input
4 0 2 2 1 3 8 6 3
Sample Output
2 3 4 1 2
题意:飞船往同一方向飞,已知每个飞船的起点(不重合)和速度,问题一:每个飞船被超过的次数的总和(模1000000);问题二:输出前10000次超越,按照时间排序,若时间相同按照超越别飞船的飞船的输入顺序排序。
解题思路:
问题一:按照起点排序(输入已经给我们排好),若前一个速度比当前的速度大,则前面那个飞船一定能超越当前飞船,否则不可能。因此,只要算一下逆序数和就可以了。
问题二:第一个超越的一定是相邻两个飞船。
反证:设当前位置为A-B-C,若第一次超越为A->C,则必定A->B或B->C,与A->C为第一次超越矛盾。
因此:
这样,我就能保证每次输入的就是当前最早超越的飞船!
顶层设计完了之后就是实现问题了,逆序数我用的是线段树。寻找超越飞船我也用了线段树,把每段线段当作一个点,然后每次查询最小,单点更新。
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> using namespace std; const int maxn1 = 250010; const int maxn2 = 110; const int mod = 1000000; struct tree1{ int l , r , sum; }a1[4*maxn2]; struct plane{ int x , v; }P[maxn1]; struct tree2{ int l , r , Max; }a2[4*maxn1]; struct Node{ int l , r; }node[maxn1]; int N; void build1(int l , int r , int k){ a1[k].l = l; a1[k].r = r; a1[k].sum = 0; if(l != r){ int mid = (l+r)/2; build1(l , mid , 2*k); build1(mid+1 , r , 2*k+1); } } void add1(int l , int r , int k){ if(l <= a1[k].l && a1[k].r <= r) a1[k].sum++; else{ int mid = (a1[k].l+a1[k].r)/2; if(mid >= r) add1(l , r , 2*k); else add1(l , r , 2*k+1); a1[k].sum = (a1[2*k].sum+a1[2*k+1].sum)%mod; } } int query1(int l , int r , int k){ if(l <= a1[k].l && a1[k].r <= r) return a1[k].sum; else{ int mid = (a1[k].l+a1[k].r)/2; if(mid >= r) return query1(l , r , 2*k)%mod; else if(l > mid) return query1(l , r , 2*k+1)%mod; else return (query1(l , mid , 2*k)+query1(mid+1 , r , 2*k+1))%mod; } } void pushup(int k){ if(a2[2*k].Max == -1 && a2[2*k+1].Max == -1) a2[k].Max = -1; else if(a2[2*k].Max == -1) a2[k].Max = a2[2*k+1].Max; else if(a2[2*k+1].Max == -1) a2[k].Max = a2[2*k].Max; else{ int lson = a2[2*k].Max , rson = a2[2*k+1].Max; int lnode = (P[node[lson].r].v-P[node[lson].l].v)*(P[node[rson].r].x-P[node[rson].l].x); int rnode = (P[node[rson].r].v-P[node[rson].l].v)*(P[node[lson].r].x-P[node[lson].l].x); if(lnode <= rnode) a2[k].Max = a2[2*k].Max; else a2[k].Max = a2[2*k+1].Max; } } void build2(int l , int r , int k){ a2[k].l = l; a2[k].r = r; a2[k].Max = -1; if(l == r){ if(P[node[l].l].v <= P[node[l].r].v) a2[k].Max = -1; else a2[k].Max = l; }else{ int mid = (l+r)/2; build2(l , mid , 2*k); build2(mid+1 , r , 2*k+1); pushup(k); } } void update(int l , int r , int k){ if(l <= a2[k].l && a2[k].r <= r){ if(P[node[l].l].v <= P[node[l].r].v) a2[k].Max = -1; else a2[k].Max = l; }else{ int mid = (a2[k].l+a2[k].r)/2; if(r <= mid) update(l , r , 2*k); else update(l , r , 2*k+1); pushup(k); } } void computing(){ for(int i = 1; i < N; i++){ node[i].l = i; node[i].r = i+1; } build2(1 , N-1 , 1); int cnt = 0; while(cnt < 10000){ if(a2[1].Max == -1) break; int m = a2[1].Max; printf("%d %d\n" , node[m].l , node[m].r); swap(node[m].l , node[m].r); update(m , m , 1); if(m-1 >= 1){ node[m-1].r = node[m].l; update(m-1 , m-1 , 1); } if(m+1 < N){ node[m+1].l = node[m].r; update(m+1 , m+1 , 1); } cnt++; } } void readcase(){ build1(1 , 100 , 1); int ans = 0; for(int i = 1; i <= N; i++){ scanf("%d%d" , &P[i].x , &P[i].v); ans = (ans+query1(P[i].v+1 , 100 , 1))%mod; add1(P[i].v , P[i].v , 1); } printf("%d\n" , ans); if(ans != 0) computing(); } int main(){ while(~scanf("%d" , &N)){ readcase(); } return 0; }
poj 2274 The Race(逆序数+线段树),布布扣,bubuko.com