POJ2274——The Race

来源:互联网 发布:it行业发展前景分析 编辑:程序博客网 时间:2024/06/11 21:38

The Race

描述
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.

题目大意
这道题目就是给你很多车的位置和速度,然后要求你求出超车事件发生的次数和超车事件的具体情况(哪两辆车发生超车事件),但是要注意同时间发生的超车要按位置排序。我看见[Discuss]里有人说担心三车共点的情况,但是题目里保证不会有这种情况。
解题思想
求超车事件发生的次数直接用二路归并求逆序对。
具体情况不能直接暴力因为空间开不下,所以我们想到模拟车的超车状态。对于每一次超车肯定发生在相邻的两辆车之间,所以我们只需要先记录相邻两辆车之间超车的时间,然后挑一个最短的时间(假设我们挑出车i-1,i),交换这两辆车,代表一次超车,这时候会出现至多两个可能的超车事件,分别是i-2,i和i-1,i+1(其中i表示位置),我们要把这个加入我们的考虑范围。因为每次都需要挑出一个最短的时间所以我们马上就会想到用堆优化(因为题目要求堆是要多关键字的,有点烦)。但是会发现从堆取出的超车事件可能是不存在的,所以需要开一个数组记录一下,具体实现如下。

#include<cstdio>#include<algorithm>using namespace std;const int maxn=250005,tt=1000000;int v[maxn],x[maxn],w[maxn],a[maxn],c[maxn];int n,len,ans;struct jz{    int x,y,w;    double t;}que[maxn];inline int  _read(){    int sum=0;char ch=getchar();    while (ch<'0'||ch>'9') ch=getchar();    while (ch>='0'&&ch<='9') sum=sum*10+ch-48,ch=getchar();    return sum;}void msort(int L,int R){    if (L>=R) return;    int mid=(L+R)/2;    msort(L,mid);msort(mid+1,R);    for (int k=L;k<=R;k++) c[k]=a[k];    int i=L,j=mid+1;    for (int k=L;k<=R;k++)    if (j>R||(i<=mid&&c[i]>=c[j])) a[k]=c[i++];else a[k]=c[j++],ans=(ans+mid-i+1)%tt;}void put(int x,double y){    que[++len].x=w[x];que[len].y=w[x-1];que[len].w=x;que[len].t=y;    int son=len;    while (son>1&&(que[son].t<que[son>>1].t||(que[son].t==que[son>>1].t&&que[son].w<que[son>>1].w))){        que[0]=que[son>>1];que[son>>1]=que[son];que[son]=que[0];        son=son>>1;    }}void get(){    que[1]=que[len];len--;int fa=1,son;    while (2*fa<=len){        if (2*fa+1>len||(que[2*fa].t<que[2*fa+1].t||(que[2*fa].t==que[2*fa+1].t&&que[2*fa].w<que[2*fa+1].w))) son=2*fa;else son=2*fa+1;        if (que[fa].t<que[son].t||(que[fa].t==que[son].t&&que[fa].w<que[son].w)) break;        que[0]=que[fa];que[fa]=que[son];que[son]=que[0];        fa=son;     }}int main(){    freopen("exam.in","r",stdin);    freopen("exam.out","w",stdout);    n=_read();    for (int i=1;i<=n;i++){        x[i]=_read();v[i]=a[n-i+1]=_read();w[i]=i;        if (i!=1&&v[i-1]>v[i]) put(i,(double)(x[i]-x[i-1])/(v[i-1]-v[i]));    }    msort(1,n);    printf("%d\n",ans);    for (int i=1;i<=10000;i++){        while (len>0&&(w[que[1].w]!=que[1].x||w[que[1].w-1]!=que[1].y)) get();        if (len==0) break;        int h=que[1].w;        printf("%d %d\n",w[h-1],w[h]);swap(w[h],w[h-1]);get();        if (h>2&&v[w[h-2]]>v[w[h-1]]) put(h-1,(double)(x[w[h-1]]-x[w[h-2]])/(v[w[h-2]]-v[w[h-1]]));         if (h<n&&v[w[h]]>v[w[h+1]]) put(h+1,(double)(x[w[h+1]]-x[w[h]])/(v[w[h]]-v[w[h+1]]));    }    return 0;}
2 0
原创粉丝点击