题目: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);
}