• [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按升序排列。

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

             时间复杂度 :O(NlogN)

    [代码]

            

    #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
    ",ans);
            
            return 0;
        
    }
  • 相关阅读:
    PHP 统计数据功能 有感
    一个高效的工作方式
    Navicat for mysql 导出sql文件 导入sql文件
    chrome浏览器,调试详解,调试js、调试php、调试ajax
    网络编程中几个地址结构与转换(in_addr,sockaddr,sockaddr_in,pcap_addr)
    TCP 协议
    tcp抓包 Wireshark 使用
    (转)linux中常用的头文件
    ubuntu安装使用kdevelop
    安卓u8800刷机
  • 原文地址:https://www.cnblogs.com/evenbao/p/9575678.html
Copyright © 2020-2023  润新知