【題目描述】
Jzabc對賽車也很感興趣,在參觀車展是,想到這樣一個問題,在某時刻,他看到n輛車(總是勻速行駛)在同一直線上,且處於一個無限長的直道上,而且n輛車有嚴格的先後之分,。他通過特殊的器材測出了每輛車的速度,那麼問題出現了,如果有車A和車B,A在B的後面,且A的速度快於B的,那麼經過一段時間後,A一定會超過B,我們稱之爲一次超車。那麼他想請你幫忙計算超車總數。我們記車道起點的座標爲0 ,沒有兩輛車的座標相同。
【輸入格式】
第一行,一個數N,表示車輛總數。以下n行爲N輛車的信息;
第二行至第N+1行,每行有兩個正整數X、Y,X和Y之間有一個空格,其中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;
}