超車 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;
}



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