51nod1107(斜率小于0的连线个数)

题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1107

先分别以 x 和 y 为第一和第二关键字从小到大排序,然后对 y 求逆序对……

一开始竟然想用线段树来做……

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;

typedef long long LL;

const LL maxn = 50000 + 10;

struct Point{
    LL x, y;
    Point() {}
    Point(LL x, LL y):x(x), y(y) {}
}P[maxn];
LL a[maxn];
LL r[maxn];
LL n;
LL ans;

int cmp(const Point& a, const Point& b){
    if (a.x == b.x){
        return a.y < b.y;
    }
    return a.x < b.x;
}

void msort(LL s, LL t){
    LL m, i, j, k;

    if (s == t) return ;
    m = (s + t) >> 1;
    msort(s, m);
    msort(m+1, t);
    i = s;
    j = m + 1;
    k = s;
    while (i <= m && j <= t){
        if (a[i] > a[j]){
            r[k++] = a[i++];
            ans += (LL)(t - j + 1);
        }else{
            r[k++] = a[j++];
        }
    }

    while (i <= m){
        r[k++] = a[i++];
    }
    while (j <= t){
        r[k++] = a[j++];
    }
    for (i=s; i<=t; i++) a[i] = r[i];
}

int main()
{
    scanf("%lld", &n);
    for (LL i=1; i<=n; i++) scanf("%lld%lld", &P[i].x, &P[i].y);

    sort(P+1, P+n+1, cmp);

    for (LL i=1; i<=n; i++) a[i] = P[i].y;
    msort(1, n);
    cout << ans << endl;

    return 0;
}


猜你喜欢

转载自blog.csdn.net/qust1508060414/article/details/76695197