燈塔 (數據結構)

燈塔(LightHouse)


Description

As shown in the following figure, If another lighthouse is in gray area, they can beacon each other.node

For example, in following figure, (B, R) is a pair of lighthouse which can beacon each other, while (B, G), (R, G) are NOT.數組

Input

1st line: Nide

2nd ~ (N + 1)th line: each line is X Y, means a lighthouse is on the point (X, Y).spa

Output

How many pairs of lighthourses can beacon each othercode

( For every lighthouses, X coordinates won't be the same , Y coordinates won't be the same )blog

Example

Input排序

3
2 2
4 3
5 1

Outputip

1

Restrictions

For 90% test cases: 1 <= n <= 3 * 105get

For 95% test cases: 1 <= n <= 106string

For all test cases: 1 <= n <= 4 * 106

For every lighthouses, X coordinates won't be the same , Y coordinates won't be the same.

1 <= x, y <= 10^8

Time: 2 sec

Memory: 256 MB

Hints

The range of int is usually [-231, 231 - 1], it may be too small.

 

解題思路:將燈塔按照x軸由大到小排序,即將問題轉化爲求y的逆序對的個數。求解逆序對能夠利用歸併排序的思路實現。

以下圖:在某次歸併的時候,左右兩個數組已經排好順序,若是遇到a[i] > a[j],則,a[j] 與a[i] 到a[n]的全部元素均構成逆序對。

 

 

在歸併排序的時候順便統計一下逆序對的個數。

 注意,要統計的逆序對個數可能很大。

代碼以下

 

#include<cstdio>
#include<cstring>
#define MAXN 4000005
#define ll long long 
using namespace std;

struct node{
    ll x;
    ll y;
} tower[MAXN];
ll des[MAXN];
struct node des1[MAXN];
int N;
ll num;
void merg(int l, int mid, int r)
{
    int i, j;
    int k;
    i = l;
    k = l;
    j = mid + 1;
    while(i <= mid && j <= r){
        if(tower[i].x < tower[j].x){
            des1[k].x = tower[i].x;
            des1[k++].y = tower[i++].y;
        }
        else{
            des1[k].x = tower[j].x;
            des1[k++].y = tower[j++].y;
        }
    }
    while(i <= mid){
        des1[k].x = tower[i].x;
        des1[k++].y = tower[i++].y;
    }
    while(j <= r){
        des1[k].x = tower[j].x;
        des1[k++].y = tower[j++].y;
    }

    for (i = l; i <= r; i++){
        tower[i].x = des1[i].x;
        tower[i].y = des1[i].y;
    }
}
void msort(int l, int r){
    if(l >= r - 1)
    {
        if(tower[l].x > tower[r].x){
            int x, y;
            x = tower[l].x;
            y = tower[l].y;
            tower[l].x = tower[r].x;
            tower[l].y = tower[r].y;
            tower[r].x = x;
            tower[r].y = y;
        }
        return;
    }
    int mid = (l + r) >> 1;
    msort(l, mid);
    msort(mid + 1, r);
    merg(l, mid, r);
}

void merge1(int l, int mid, int r)
{
    int i, j;
    ll cnt = 0;
    int k = l;
    i = l;
    j = mid + 1;
    while(i <= mid && j <= r){
        if(tower[i].y < tower[j].y){
            des[k++] = tower[i++].y;
            cnt += r - j + 1;
        }
        else{
            des[k++] = tower[j++].y;
        }
    }
    while(i <= mid)
        des[k++] = tower[i++].y;
    while(j <= r)
        des[k++] = tower[j++].y;
    for (i = l; i <= r; i++){
        tower[i].y = des[i];
    }
    num += cnt;
}
void get_num(int l, int r)
{
    if(l >= r - 1){
        if(tower[l].y < tower[r].y){
            num++;
        }
        else{
            int temp = tower[l].y;
            tower[l].y = tower[r].y;
            tower[r].y = temp;
        }
        return;
    }
    int mid = (l + r) >> 1;
    get_num(l, mid);
    get_num(mid + 1, r);
    merge1(l, mid, r);
}

int main()
{
    scanf("%d", &N);
    num = 0;
    for (int i = 0; i < N; i++)
    {
        scanf("%lld %lld", &tower[i].x, &tower[i].y);
    }
    msort(0, N - 1);
    get_num(0, N - 1);
    printf("%lld\n", num);
    
   
    return 0;
}
View Code
相關文章
相關標籤/搜索