zoukankan      html  css  js  c++  java
  • hihocoder-1524-逆序对

    hihocoder-1524-逆序对

    #1524 : 逆序对

    时间限制:10000ms
    单点时限:1000ms
    内存限制:256MB

    描述

    给定一个1-N的排列A1, A2, ... AN,如果Ai和Aj满足i < j且Ai > Aj,我们就称(Ai, Aj)是一个逆序对。  

    求A1, A2 ... AN中所有逆序对的数目。  

    输入

    第一行包含一个整数N。  

    第二行包含N个两两不同整数A1, A2, ... AN。(1 <= Ai <= N)  

    对于60%的数据 1 <= N <= 1000  

    对于100%的数据 1 <= N <= 100000

    输出

    一个整数代表答案

    样例输入
    5
    3 2 4 5 1
    样例输出
    5

    经典的用merge sort 来解决逆序对的问题。

    #include <cstdio> 
    const int MAXN = 1e5 + 10; 
    const int MOD = 1000000007; 
    
    int  num[MAXN], tmp[MAXN]; 
    long long cnt; 
    
    void Merge_Sort(int l, int r){
        int mid = l + (r - l)/2; 
        int p = l, p1 = l, p2 = mid + 1; 
        while(p1<=mid && p2<=r){
            if(num[p1] > num[p2]){
                tmp[p++] = num[p2++]; 
                cnt += (mid - p1 + 1); 
            }else{
                tmp[p++] = num[p1++]; 
            }
        }
        while(p1<=mid){
            tmp[p++] = num[p1++]; 
        }
        while(p2<=r){
            tmp[p++] = num[p2++]; 
        }
        for(int i=l; i<=r; ++i){
            num[i] = tmp[i]; 
        } 
    }
    
    void Merge(int l, int r){
        if(l >= r ){ return; } 
        int mid = l + (r - l)/2; 
        Merge(l, mid); 
        Merge(mid+1, r); 
        Merge_Sort(l, r); 
    }
    
    int main(){
        int n; 
        while(scanf("%d", &n) != EOF){
            for(int i=0; i<n; ++i){
                scanf("%d", &num[i]); 
            }
            cnt = 0; 
            Merge(0, n-1); 
            printf("%lld
    ", cnt );
        }
        return 0; 
    }
    

      

    方法二,参考了网友的answer,因为 num 的range 是 [1, n] , 所以,可以采用树状数组。只需要对 num 一个一个插入到 dp[] 数组中,快速计算 sum即可。

    #include <cstdio> 
    #include <cstring>
    const int MAXN = 1e5 + 10; 
    const int MOD = 1000000007; 
    
    long long cnt; 
    int n, num[MAXN], dp[MAXN]; 
    
    int lowbit(int x){
        return x & -x; 
    }
    
    long long GetSum(int pt){
        long long ans = 0; 
        int i = pt; 
        while(i <= n){
            ans += dp[i]; 
            i +=  lowbit(i); 
        } 
        return ans; 
    }
    
    void AddNum(int pt, int v){
        int i = pt; 
        while(i > 0){
            dp[i] += v; 
            i -= lowbit(i); 
        }
    }
    
    int main(){
        freopen("in.txt", "r", stdin); 
    
        while(scanf("%d", &n) != EOF){
            for(int i=0; i<n; ++i){
                scanf("%d", &num[i]); 
            }
            memset(dp, 0, sizeof(dp)); 
            cnt = 0; 
            for(int i=0; i<n; ++i){
                cnt += GetSum(num[i]); 
                AddNum(num[i], 1); 
            }
            printf("%lld
    ", cnt );
        }
        return 0; 
    }
    

      

  • 相关阅读:
    linux awk命令详解
    世界上最差的系统就是linux,双击不能安装软件
    硬盘安装CentOS 6.0(超级详细图文教程)
    Vim+cscope+ctags+tags阅读源代码
    使用vim看代码:cscope
    解决面板里没有network manager图标的问题
    【b804】双栈排序
    【BZOJ 1002】[FJOI2007]轮状病毒
    【BZOJ 1004】 [HNOI2008]Cards
    【t018】派对
  • 原文地址:https://www.cnblogs.com/zhang-yd/p/7383814.html
Copyright © 2011-2022 走看看