[NOIP2013] 火柴排队

[题目链接]

        https://loj.ac/problem/2609

[算法]

         首先将式子化简 :

         sigma( (ai - bi) ^ 2) = sigma( ai^2 + bi^2 - 2aibi ) 

         显然 , 只需最大化aibi就能最小化“距离”

         考虑贪心 , 将a中最小元素与b中最小元素组合 , a中第二小与b中第二小组合 ... , 不难证明这样是最优的 ,

         因为 : 设a < b , c < d , 将a与c组合 , b与d组合比a与d组合 , b与c组合更优。

         不妨先将a和b升序排序 ,记录每个元素的初始位置 , 构造新序列p, 令p[a[i].id] = b[i].id , 问题就转化为了 , 每次可以交换相邻两个元素 , 要求用最少的次数时p按升序排列。

         只需求出逆序对数即可。 可以用归并排序或树状数组实现 , 笔者使用的是树状数组

[代码]

        

#include<bits/stdc++.h>
using namespace std;
#define MAXN 100010
const int P = 99999997;

struct info
{
        int value;
        int id;
} a[MAXN],b[MAXN];

int n,ans;
int c[MAXN];

template <typename T> inline void read(T &x)
{
    int f = 1; x = 0;
    char c = getchar();
    for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; 
    for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
    x *= f;
}
struct Binary_Indexed_Tree
{
        int c[MAXN];    
        inline int lowbit(int x)
        {
                return x & (-x);
        }
        inline void modify(int pos,int val)
        {
                for (int i = pos; i <= n; i += lowbit(i)) c[i] = (c[i] + val) % P;
        }
        inline int query(int pos)
        {
                int ret = 0;
                for (int i = pos; i; i -= lowbit(i)) ret = (ret + c[i]) % P;
                return ret;
        }
} BIT;
inline bool cmp(info a,info b) { return a.value < b.value; }
int main() 
{
        
        read(n);
        for (int i = 1; i <= n; i++) 
        {
                read(a[i].value);
                a[i].id = i;
        }
        for (int i = 1; i <= n; i++) 
        {
                read(b[i].value);
                b[i].id = i;
        }
        sort(a + 1,a + n + 1,cmp);
        sort(b + 1,b + n + 1,cmp);
        for (int i = 1; i <= n; i++) c[a[i].id] = b[i].id;
        for (int i = 1; i <= n; i++)
        {
                ans = (ans + (i - BIT.query(c[i] - 1) - 1) % P + P) % P;
                BIT.modify(c[i],1);        
        }
        printf("%d\n",ans);
        
        return 0;
    
}

猜你喜欢

转载自www.cnblogs.com/evenbao/p/9575678.html