清华数据结构PA3——灯塔(LightHouse)

题目:https://dsa.cs.tsinghua.edu.cn/oj/problem.shtml?id=1144

看起来很难处理,不过邓老师在课上已经提示过了,其实就是将x看作数组下标,y看作该下标所处位置的值,然后考察存在的顺序对的个数。这个考察可以通过归并排序的归并来解决。

#include<iostream>
#define MAXSIZE 4000000
using namespace std;
struct Point
{
	long long x, y;
};
struct Point point[MAXSIZE];
long long times = 0;
long long value[MAXSIZE];
void mergex(Point* point, int low, int mid, int high)
{
	Point* A = point + low;
	int lb = mid - low;
	Point* B = new Point[lb];
	for (int i = 0; i < lb; B[i] = A[i++]);
	int lc = high - mid;
	Point* C = point + mid;
	for (int i = 0, j = 0, k = 0; (j<lb)||(k<lc); )
	{
		if ((j<lb)&&((lc<=k)||(B[j].x<=C[k].x)))
		{
			A[i++] = B[j++];
		}
		if ((k<lc)&&((lb<=j)||(C[k].x< B[j].x)))
		{
			A[i++] = C[k++];
		}
	}
	delete[] B;
}

void x_mergesort(Point* point,int low,int high)
{
	if (high-low<2)
	{
		return;
	}
	int mid = (high + low) / 2;
	x_mergesort(point, low, mid);
	x_mergesort(point, mid, high);
	mergex(point, low, mid, high);
}

void mergey(long long* value, int low, int mid, int high)
{
	long long* A = value + low;
	int lb = mid - low;
	long long* B = new long long[lb];
	for (int i = 0; i < lb; B[i] = A[i++]);
	int lc = high - mid;
	long long* C = value + mid;
	for (int i = 0, j = 0, k = 0; (j < lb) || (k < lc); )
	{
		if ((j < lb) && ((lc <= k) || (B[j] <= C[k])))
		{
			A[i++] = B[j++];
			if (k < lc)
			{
				times = times + (lc - k);
			}
		}
		if ((k < lc) && ((lb <= j) || (C[k] < B[j])))
		{
			A[i++] = C[k++];
		}
	}
	delete[] B;
}

void y_mergesort(long long* value, int low, int high)
{
	if (high - low < 2)
	{
		return;
	}
	int mid = (high + low) / 2;
	y_mergesort(value, low, mid);
	y_mergesort(value, mid, high);
	mergey(value, low, mid, high);
}

int main() 
{
	int n, x, y;
	scanf("%d", &n);
	for (int i = 0; i < n; i++)
	{
		scanf("%lld %lld", &point[i].x, &point[i].y);
	}
	x_mergesort(point, 0, n);
	for (int i = 0; i < n; i++)
	{
		value[i] = point[i].y;
	}
	y_mergesort(value, 0, n);
	printf("%lld\n", times);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值