zoukankan      html  css  js  c++  java
  • b_lq_小朋友排队(归并排求逆序对+前n项和)

    某个小朋友第 k 次交换时,他的不高兴程度增加 k。
    请问,要让所有小朋友按从低到高排队,他们的不高兴程度之和最小是多少。

    输入:
    3
    3 2 1
    输出:9
    解释:<3,2>交换(2,3,1),<3,1>交换(2,1,3),<1,2>交换(1,2,3)
    1、2、3都被交换了两次,所以不开心值都为1+2=3,总为9
    

    思路
    这其实就是在求每个数字在逆序对中出现的次数

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=1e6+5;
    struct node {
        ll h,c;
    } a[N], b[N];
    void merge_sort(int l, int r) {
        if (l==r) return;
        int m=l+r>>1;
        merge_sort(l,m), merge_sort(m+1, r);
        int i=l, j=m+1, k=l;
        while (i<=m && j<=r) {
            //a[i].h<=a[j].h,则证明[m,j]的身高都不比a[i]高。为什么?因为只有a[i]>a[j]时,指针j才会移动
            if (a[i].h<=a[j].h) b[k]=a[i++], b[k++].c+=j-m-1;
            else                b[k]=a[j++], b[k++].c+=m-i+1;
        }
        while (i<=m) b[k]=a[i++], b[k++].c+=j-m-1; //i没有走完,表示[m,j]这些人的身高都小于a[i].h,也就是和a[i].h组成了j-m-1个逆序对
        while (j<=r) b[k]=a[j++], b[k++].c+=m-i+1; //j没有走完,表示[
        for (int p=l; p<=r; p++) a[p]=b[p];
    }
    int main() {
        std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
        int n; cin>>n;
        for (int i=0; i<n; i++) cin>>a[i].h, a[i].c=0;
        merge_sort(0,n-1);
        ll ans=0;
        for (int i=0; i<n; i++) {
            ll x=a[i].c;
            ans+=(x+1)*x/2ll;
        }
        cout<<ans;
        return 0;
    }
    
  • 相关阅读:
    Xcode 增强开发效率的插件
    svn 常用指令
    初识JFinal
    企业竞争案例分析
    可行性研究5
    可行性研究习题4
    可行性研究课后题
    关于阅读软件工程和计算机科学技术区别的文章来谈谈自己看法
    关于中文编程是解决中国程序员效率的秘密武器的问题思考
    Java ForkJoinPool 用法及原理
  • 原文地址:https://www.cnblogs.com/wdt1/p/13764818.html
Copyright © 2011-2022 走看看