二維平面上n個點之間共有c(n,2)條連線。求這c(n,2)條線中斜率小於0的線的數量。
二維平面上的乙個點,根據對應的x y座標可以表示為(x,y)。例如:(2,3) (3,4) (1,5) (4,6),其中(1,5)同(2,3)(3,4)的連線斜率 < 0,因此斜率小於0的連線數量為2。
input
第1行:1個數n,n為點的數量(0 <= n <= 50000)output第2 - n + 1行:n個點的座標,座標為整數。(0 <= x[i], y[i] <= 10^9)
輸出斜率小於0的連線的數量。(2,3) (2,4)以及(2,3) (3,3)這2種情況不統計在內。input 示例
4output 示例2 33 4
1 54 6
2
這道題目還有另外乙個表述就是求斜率大於0的數量,其實本質是一樣的。
一看題目的資料量,就知道肯定不能直接列舉。
首先稍微分析一下我們發現,斜率小於0的情況的直線就是直角座標系中經過二四象限的直線,由於所有點都在第一象限,所以說,如果兩個點滿足斜率小於0,比如(x1,y1)(x2,y2)一定滿足(x2>x1,y1>y2)或者相反(x1>x2,y2>y1)。其實也就是經過二四象限直線上的點滿足的條件。
那麼既然如此,我們可以先對x從小到大排序,那麼對於每乙個點,能夠和這個點組成斜率小於0的點就是後面所有點中縱座標y小於當前點縱座標的點,那麼直線的數量也就是比當前y值小的點的個數。判斷到這裡,一般人都會想到列舉,直接對於每乙個點,求後面y值小於當前y值的點的個數,然後求和即可。但是這樣可定會超時。
對於逆序數熟悉的人,就會發現,y值大於後面的y值,實際上就是逆序數。什麼是逆序數,就是每個數有乙個下標i,j;當ia[j]那麼這就是乙個逆序數對。
因此,求所有y點,後面小於他的點的個數的總和,其實就是求由y座標組成的序列的逆序對數。
逆序對數很明顯,歸併排序直接就解決了。
這裡注意乙個細節,那就是斜率不存在以及斜率為0的情況如何規避。斜率為0的也就是y值一樣的,這裡求逆序數的時候不判斷相等即可規避。斜率不存在也就是x相同的,如何規避呢,這裡就是在按x排序的時候,如果兩個點的x一樣,那麼他們的y就從小到大排序,這樣對於x一樣的點就不會有逆序對,這樣當然後面求逆序對的時候也就不會計算在內了。
#include#include #include using namespace std;
const int maxn = 50002;
typedef struct point
point;
point point[maxn];
int n;
__int64 sum;
bool cmp(const point &a, const point &b)
return a.x < b.x;
}void merge(vector&y,int l, int mid, int r)
for (int i = mid + 1; i <= r; ++ i)
int p = 0,q = 0,k = l;
while (p < l.size() && q < r.size())
else
}while (p&y,int l, int r)
}int main()
sort(point,point+n,cmp);
vectory;
for (int i = 0; i < n; ++ i)
mergesort(y,0,n-1);
cout << sum << endl;
} return 0;
}
斜率小於0的連線數量
二維平面上n個點之間共有c n,2 條連線。求這c n,2 條線中斜率小於0的線的數量。二維平面上的乙個點,根據對應的x y座標可以表示為 x,y 例如 2,3 3,4 1,5 4,6 其中 1,5 同 2,3 3,4 的連線斜率 0,因此斜率小於0的連線數量為2。input 第1行 1個數n,n為...
1107 斜率小於0的連線數量
二維平面上n個點之間共有c n,2 條連線。求這c n,2 條線中斜率小於0的線的數量。二維平面上的乙個點,根據對應的x y座標可以表示為 x,y 例如 2,3 3,4 1,5 4,6 其中 1,5 同 2,3 3,4 的連線斜率 0,因此斜率小於0的連線數量為2。input 第1行 1個數n,n為...
1107 斜率小於0的連線數量
二維平面上n個點之間共有c n,2 條連線。求這c n,2 條線中斜率小於0的線的數量。二維平面上的乙個點,根據對應的x y座標可以表示為 x,y 例如 2,3 3,4 1,5 4,6 其中 1,5 同 2,3 3,4 的連線斜率 0,因此斜率小於0的連線數量為2。input 第1行 1個數n,n為...