题目: 灯塔LightHouse
简要描述: 等效成给定n个坐标,统计坐标轴上两点x y方向只差是同向的,n点的x y坐标不会有重叠.

思路:
1. 对n点循环遍历,对两点做差值,满足y x方向同时大于或小于,那么累计+1->题目中给定数量级10^6,
时间复杂度太大,O(n!),不可用
2. 先对x方向进行排序,再统计y方向的相对顺序,如果y方向的也是顺序的,那么这两点必然满足条件+1
3. 需进行两次排序,采用归并排序将时间复杂度降为nlogn, 第一次对x方向上归并排序,第二次对y
方向上进行归并排序,同时对顺序对计数.

假设各级子序列的归并排序已经完成,只剩下A B两个区间,那么可以保证A中所有元素x都比B中元素小,
合并子序列的时候如果A[i]y方向小于B[j],那么j及j后所有元素都应该统计为顺序对中.

实现
1. 读入元素后进行两次归并排序
2. 归并排序双路合并函数中区分出x方向排序和y方向排序,y方向排序同时进行计数
3. 双路合并函数中如果动态分配存储空间用于临时存储数组,10%超时,改成全局数组后95%用例通过,
仍有5%不行,瓶颈应该还是数组for循环的赋值,没有想到啥办法.

代码

cpp#include <stdio.h> 
struct points
{
    int x;
    int y;
};
// global
bool isBeacon(points lighthouse1, points lighthouse2);
void merge(int lo, int mi, int hi, int flag=1);
void mergeSort(int lo, int hi, int flag=1);
int irow = 0;
long iTotalNum = 0;

points pointsLocate[4000000] = {};
points  B[4000000] = {};
void getInputNum()
{
    scanf("%d", &irow);

    for(int i=0; i<irow; i++)
    {
        int temp1, temp2;
        scanf("%d %d", &temp1, &temp2);
        pointsLocate[i].x = temp1;
        pointsLocate[i].y = temp2;
    }
}

bool lower_x(points left, points right)
{
    return (left.x < right.x);
}
bool lower_y(points left, points right)
{
    return (left.y < right.y);
}

void merge(int lo, int mi, int hi, int flag)
{
    //points *B = new points[mi-lo];
    int lb = mi - lo;
    int j = lo;
    int i=0;
    for(; i<lb;)
    {
        B[i] = pointsLocate[j];
        i++;
        j++;
    }
    int lc = hi-mi;
    points *A = &pointsLocate[lo];
    points *C = &pointsLocate[mi];

    if(flag == 1)
    {
        for(int i=0, j=0, k=0; j<lb || k<lc;)
        {
            if(j<lb && (lc <= k || lower_x(B[j], C[k])))    A[i++] = B[j++];
            if(k<lc && (lb <= j || lower_x(C[k], B[j])))    A[i++] = C[k++];
        }
    }
    else
    {
        for(int i=0, j=0, k=0; j<lb || k<lc;)
        {
            if(j<lb && (lc <= k || lower_y(B[j], C[k])))    
            {
                if(lower_y(B[j], C[k])) 
                {
                    iTotalNum += lc-k;
                //  printf("%d-%d-%d\n", lo, hi, lc-k);
                }
                A[i++] = B[j++];
            }
            else if(k<lc && (lb << j || lower_y(C[k], B[j])))   

                A[i++] = C[k++];
        //      iTotalNum += lb-j;
            }
    }

    //delete B;
}

//nlogn
void mergeSort(int lo, int hi, int flag)
{
    if(hi - lo < 2) return;
    int mi = (lo+hi) >> 1;
    mergeSort(lo, mi, flag);
    mergeSort(mi, hi, flag);
    merge(lo, mi, hi, flag);
}

int main()
{
#ifndef _OJ_
freopen("inputlight.txt", "r", stdin);
#endif
    getInputNum();
    mergeSort(0, irow, 1);
    mergeSort(0, irow, 2);

    printf("%ld\n", iTotalNum);
    return 0;
}

//n^2复杂度
bool isBeacon(points lighthouse1, points lighthouse2)
{
    if(lighthouse1.x>lighthouse2.x && lighthouse1.y>lighthouse2.y)
      return true;
    if(lighthouse1.x<lighthouse2.x && lighthouse1.y<lighthouse2.y)
      return true;
    return false;
}

Ender
599 声望17 粉丝