NOIP2013提高组火柴排队

Posted ssttkkl

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NOIP2013提高组火柴排队相关的知识,希望对你有一定的参考价值。

https://www.luogu.org/problem/show?pid=1966

Σ(ai-bi)2=Σai2+Σbi2-2Σai*bi,要使Σ(ai-bi)2最小,则需2Σai*bi最大。

由排序不等式可知两列数字里第一大与第一大对应,第二大与第二大对应,……,第k大与第k大对应,……,第n大与第n大对应时,Σai*bi最大。

故先将第一列每个数字映射到第二列排名相同的数字,再求需要交换的次数,也就是逆序对的个数。

#include <algorithm>
#include <iostream>
#include <vector>
#define maxn 100005
typedef long long llint;
using namespace std;
int n;
llint tmp[maxn], sorted[maxn], cnt = 0;
void merge_sort(int l, int r)
{
    if (l == r)
        return;

    int mid = (l + r) / 2;
    merge_sort(l, mid);
    merge_sort(mid + 1, r);

    int p1 = l, p2 = mid + 1, p = l;
    while (p1 <= mid && p2 <= r)
    {
        if (sorted[p1] <= sorted[p2])
            tmp[p++] = sorted[p1++];
        else
        {
            cnt = (cnt + (mid - p1 + 1)) % 99999997;
            tmp[p++] = sorted[p2++];
        }
    }

    while (p1 <= mid)
        tmp[p++] = sorted[p1++];
    while (p2 <= r)
        tmp[p++] = sorted[p2++];

    for (int i = l; i <= r; i++)
        sorted[i] = tmp[i];
}
template <class T> void print(T *p)
{
    for (int i = 1; i <= n; i++)
        cout << p[i] <<  ; 
    cout << endl;
}
pair<llint, llint> a[maxn], b[maxn];
int rnk[maxn];
int main()
{
    ios::sync_with_stdio(false);
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i].first;
        a[i].second = i; 
    }
    for (int i = 1; i <= n; i++)
    {
        cin >> b[i].first;
        b[i].second = i; 
    }
    sort(a + 1, a + n + 1);
    sort(b + 1, b + n + 1);
    
    for (int i = 1; i <= n; i++)
        sorted[a[i].second] = b[i].second; // 将第一列排第i名的项与第二列排第i名的项对应
    merge_sort(1, n);
    cout << cnt << endl;
    return 0;
}

 

以上是关于NOIP2013提高组火柴排队的主要内容,如果未能解决你的问题,请参考以下文章

[NOIP2013提高组]火柴排队

noip2013提高组day1第二题火柴排队

noip提高组2013 火柴排队

火柴排队——noip2013——提高组

NOIP2013提高组火柴排队

刷提总结——火柴排队(NOIP2013)