1. 程式人生 > >bzoj 2441 [中山市選2011]小W的問題

bzoj 2441 [中山市選2011]小W的問題

bzoj 2441 [中山市選2011]小W的問題

Description

有一天,小W找了一個笛卡爾座標系,並在上面選取了N個整點。他發現通過這些整點能夠畫出很多個“W”出來。具體來說,對於五個不同的點(x1, y1), (x2, y2), (x3, y3), (x4, y4), (x5, y5),如果滿足:

·x1 < x2 < x3 < x4 < x5

·y1 > y3 > y2

·y5 > y3 > y4

則稱它們構成一個“W”形。

現在,小W想統計“W”形的個數,也就是滿足上面條件的五元點組個數。你能幫助他嗎?

Input

第一行包含一個整數N,表示點的個數。

下面N行每行兩個整數,第i+1行為(xi, yi),表示第i個點的座標。

Output

僅包含一行,為“W”形個數模1 000 000 007的值。

Sample Input

6

1 10

2 1

3 5

4 6

5 1

6 10

Sample Output

3

HINT

對於100%的資料滿足N ≤ 200 000,0 ≤ xi ≤ 10^9,0 ≤ yi ≤ 10^9

Solution

第一次做這道題可能是八九個月之前了,當時看題解看了半天,今天重做了一遍,感覺還是細節多到爆炸

NewTrain 裡面有好幾道這樣給定平面上的點計數的問題,套路基本都差不多

首先一個明顯的想法就是把 'W' 變成兩個 'V'

那麼題目轉化成求 'V' 形狀的個數,並且把他記錄在 'V' 的某一個端點上

最後計算答案就是把每個點當做兩個 'V' 的公共點求一個答案

現在我們把形狀轉化成三元組,比如三元組 (1,2,3)表示的是一個三個點上升的形狀,就是 x1 < x2 < x3, y1 < y2 < y3,而題目裡的三元組就是 (3,1,2) 和 (2,1,3) ,公共點就是 2

兩種形狀的統計是等價的,所以只討論把 (3,1,2) 的個數並且記錄在 2 上

有一種比較暴力的做法,按照縱座標排序,每個點上面的數表示未插入的序列(也就是縱座標比他大的點中橫座標比他小的的點,實際上就是他左上角的點數量),那麼以 i 這個位置為 2 的 (3,1,2) 的個數就是他左下角的點對應的數的和,因為現在在未插的數都是大於 i 的縱座標的。

考慮怎麼維護這個東西,計數的過程比較簡單,就是樹狀陣列統計插入的點的橫座標及其對應的數。

修改的時候,事實上每插入一個點就會對未插入序列中橫座標比他大的所有點影響,使他們的數減去 1

這種做法比較暴力,而且在有相等座標的時候細節較多

下面有一種比較精妙的做法

我們考慮(2,1,3) 的個數

很顯然不好做,所以考慮容斥

網上說直接用 (?,?,3) - (1,2,3) 就可以了,但是我不明白這樣怎麼能統計到 2 這個位置上,我覺得這樣只能放在 3 上,然後就爆炸了

後來我自己想了一個複雜一點的容斥,考慮當前點是 i,我們將每個點的權值設為這個點的右側的點的個數,那麼考慮 i 右側所有縱座標小於 i 的點的權值和 - (3,2,1) - (3,1,2) 就是答案了

這樣比第一種做法好寫好調得多

綜上所述,這題出的純粹為了噁心人(你說明明會了 'v' 就會 'w',他硬是要你寫兩遍不同方向的,而且明明可以出成橫縱座標都不相等,可以方便得多)

程式碼就不附了,比較醜陋