超车 OVERTAKING

【题目描述】

Jzabc对赛车也很感兴趣,在参观车展是,想到这样一个问题,在某时刻,他看到n辆车(总是匀速行驶)在同一直线上,且处于一个无限长的直道上,而且n辆车有严格的先后之分,。他通过特殊的器材测出了每辆车的速度,那么问题出现了,如果有车A和车BAB的后面,且A的速度快于B的,那么经过一段时间后,A一定会超过B,我们称之为一次超车。那么他想请你帮忙计算超车总数。我们记车道起点的座标为,没有两辆车的座标相同。

【输入格式】

第一行,一个数N,表示车辆总数。以下n行为N辆车的信息;

第二行至第N+1行,每行有两个正整数XYXY之间有一个空格,其中X为车的座标,Y为车的速度。

0<=X,Y<=1000000000

【输出格式】

一行,超车总数

【输入样例】

2

5 6

2 8

【输出样例】

1

【数据规模】

对于20%的数据,满足N<=300

对于50%的数据,满足N<=3000

对于100%的数据,满足N<=300000



由于位置不同

按位置第一关键字排序后

找速度中的逆序对 即为超车数

因为路是无限长的

存在一组I,J使I位置在J左面 I速度大于J

I就一定会超过J


可以利用归并排序在NlogN时间内求出逆序对

第一次写归并= =

wa了好多次


加入找到t[h1]>t[h2]则需要加上mid-h1+1

因为l-mid已经归并好

t[h1]>t[h2] 则对于h1<=i<=mid  t[i]>t[h2]


#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct self{int x,y;}s[500033];

int cmp(self a1,self a2){return a1.x<a2.x;}

int m,a,b,c,d,t[500033],temp[500033];
long long z;

void gui(int l,int r)
{
    
    int mid=(l+r)>>1;
    int h1=l,h2=mid+1,i=0;
    while(h1<=mid&&h2<=r)
    {
        if(t[h1]<=t[h2])
        {
            i++;
            temp[i]=t[h1];
            h1++;
        }
        else
        {
            z=z+(mid-h1+1);
            i++;
            temp[i]=t[h2];
            h2++;
        }
    }
    while(h1<=mid)
    {
        i++;
        temp[i]=t[h1];
        h1++;
    }
    while(h2<=r)
    {
        i++;
        temp[i]=t[h2];
        h2++;
    }
    for(a=l;a<=r;a++)t[a]=temp[a-l+1];
}

void work(int l,int r)
{
    if(l==r)return;
    int mid=(l+r)>>1;
    work(l,mid);
    work(mid+1,r);
    gui(l,r);
}
    
int main()
{
    freopen("overtaking.in","r",stdin);freopen("overtaking.out","w",stdout);
    scanf("%d",&m);
    for(a=1;a<=m;a++)scanf("%d%d",&s[a].x,&s[a].y);
    sort(s+1,s+m+1,cmp);
    for(a=1;a<=m;a++)t[a]=s[a].y;
    work(1,m);
    cout<<z<<endl;
    
    return 0;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章