zoukankan      html  css  js  c++  java
  • HDU

    题意:给定一个序列,求分别将前m个数移到序列最后所得到的序列中,最小的逆序数。

    分析:m范围为1~n,可得n个序列,求n个序列中最小的逆序数。

    1、将序列从头到尾扫一遍,用query求每个数字之前有多少个大于该数字的数,方法如下。

    (1)将已经扫过的数字所对应的位置标记,通过query求该数字之后有多少个数被标记过

    (2)该数字之后所有被标记的数字,都是在该数字之前出现过的(i<j),而这些数字又大于该数字(ai>aj),因此该数字之后所有的标记和就是该数字之前比该数字大的数的个数。

    2、sum为初始序列的逆序和,从前往后依次将每个数字移到序列最后。

    假设当前把a[i]移到序列最后,则

    后一个序列B的逆序和=前一个序列A的逆序和 - a[i] + (n - 1 - a[i])。

    eg:假设前一个序列A为3 6 9 0 8 5 7 4 2 1,则a[i]为3。

    a[i]是序列A的第一个数,a[i]后面的数中有a[i]个数小于a[i](分别为0,2,1),因此把a[i]移到最后,会减少a[i]个逆序数。

    而a[i]后面的数中有 (n - 1 - a[i])个数大于a[i],因此把a[i]移到最后,会增加 (n - 1 - a[i])个逆序数。

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<cctype>
    #include<cmath>
    #include<iostream>
    #include<sstream>
    #include<iterator>
    #include<algorithm>
    #include<string>
    #include<vector>
    #include<set>
    #include<map>
    #include<stack>
    #include<deque>
    #include<queue>
    #include<list>
    #define lowbit(x) (x & (-x))
    const double eps = 1e-8;
    inline int dcmp(double a, double b){
        if(fabs(a - b) < eps) return 0;
        return a > b ? 1 : -1;
    }
    typedef long long LL;
    typedef unsigned long long ULL;
    const int INT_INF = 0x3f3f3f3f;
    const int INT_M_INF = 0x7f7f7f7f;
    const LL LL_INF = 0x3f3f3f3f3f3f3f3f;
    const LL LL_M_INF = 0x7f7f7f7f7f7f7f7f;
    const int dr[] = {0, 0, -1, 1, -1, -1, 1, 1};
    const int dc[] = {-1, 1, 0, 0, -1, 1, -1, 1};
    const int MOD = 1e9 + 7;
    const double pi = acos(-1.0);
    const int MAXN = 5000 + 10;
    const int MAXT = 10000 + 10;
    using namespace std;
    int a[MAXN];
    int cnt[MAXN << 2];
    void update(int k, int id, int L, int R){
        if(L == R){
            ++cnt[id];
        }
        else{
            int mid = L + (R - L) / 2;
            if(k <= mid) update(k, id << 1, L, mid);
            else update(k, id << 1 | 1, mid + 1, R);
            cnt[id] = cnt[id << 1] + cnt[id << 1 | 1];
        }
    }
    int query(int l, int r, int id, int L, int R){
        if(l <= L && R <= r){
            return cnt[id];
        }
        int mid = L + (R - L) / 2;
        int ans = 0;
        if(l <= mid) ans += query(l, r, id << 1, L, mid);
        if(r > mid) ans += query(l, r, id << 1 | 1, mid + 1, R);
        return ans;
    }
    int main(){
        int n;
        while(scanf("%d", &n) == 1){
            memset(cnt, 0, sizeof cnt);
            int sum = 0;
            for(int i = 0; i < n; ++i){
                scanf("%d", &a[i]);
                sum += query(a[i] + 1, n, 1, 1, n);
                update(a[i] + 1, 1, 1, n);
            }
            int ans = sum;
            for(int i = 0; i < n; ++i){
                sum = sum - a[i] + (n - 1 - a[i]);
                ans = min(ans, sum);
            }
            printf("%d
    ", ans);
        }
        return 0;
    }
    

     

  • 相关阅读:
    无缝衔接 gRPC 与 dubbo-go
    阿里员工一天有26小时,怎么做到的?
    小米流式平台架构演进与实践
    基于 Flink 构建 CEP 引擎的挑战和实践
    实时计算在贝壳的实践
    阿里巴巴大规模应用Flink的踩坑经验:如何大幅降低 HDFS 压力?
    我要上官网,上云案例征集活动启动啦! 提交案例,得大奖!【阿里云】
    【原】git常用命令笔记
    【原】使用vue2+vue-router+vuex写一个cnode的脚手架
    【原】老生常谈-从输入url到页面展示到底发生了什么
  • 原文地址:https://www.cnblogs.com/tyty-Somnuspoppy/p/7275053.html
Copyright © 2011-2022 走看看