zoukankan      html  css  js  c++  java
  • 求逆序数的两个方法

    1.归并排序

    #include <iostream>
    
    using namespace std;
    
    const int maxn = 1000;
    
    int a[maxn],b[maxn];
    int ans;
    
    void merge_sort(int x,int y){
        if(y-x>1)
        {
            int m = x+(y-x)/2;
            int p = x, q = m,i = x;
            merge_sort(x,m);
            merge_sort(m,y);
            while(p<m||q<y){
                if(q>=y||(p<m&&a[p]<=a[q])) b[i++] = a[p++];
                else {b[i++]=a[q++];ans+=m-p;}
            }
            for(int i = x;i<y;i++) a[i] = b[i];
        }
    }
    
    int main()
    {
        int n;
        while(cin>>n){
           for(int i=0;i<n;i++) cin>>a[i];
           ans=0;
           merge_sort(0,n);
           cout<<ans<<endl;
           for(int i=0;i<n;i++) cout<<a[i]<<" ";cout<<endl;
        }
        return 0;
    }
    View Code

    2.离散+树状数组

    E. Infinite Inversions
    time limit per test
    2 seconds
    memory limit per test
    256 megabytes
    input
    standard input
    output
    standard output

    There is an infinite sequence consisting of all positive integers in the increasing order: p = {1, 2, 3, ...}. We performed n swap operations with this sequence. A swap(a, b) is an operation of swapping the elements of the sequence on positions a and b. Your task is to find the number of inversions in the resulting sequence, i.e. the number of such index pairs (i, j), that i < j and pi > pj.

    Input

    The first line contains a single integer n (1 ≤ n ≤ 105) — the number of swap operations applied to the sequence.

    Each of the next n lines contains two integers ai and bi (1 ≤ ai, bi ≤ 109, ai ≠ bi) — the arguments of the swap operation.

    Output

    Print a single integer — the number of inversions in the resulting sequence.

    Sample test(s)
    input
    2
    4 2
    1 4
    output
    4
    input
    3
    1 6
    3 4
    2 5
    output
    15
    Note

    In the first sample the sequence is being modified as follows: . It has 4 inversions formed by index pairs (1, 4), (2, 3), (2, 4) and (3, 4).

    离散:

    逆序数组:9 1  0 5 4 --> 5 2 1 4 3

    这题有点特别:就是先把那些交换的点+那些中间的点(等价的几个,所以a[i].yy可能大于1)

    注意:maxn要为4*1e5,因为不单只2倍的10的5次方操作!

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <vector>
    #include <algorithm>
    #include <queue>
    #include <cmath>
    #include <stack>
    #include <iomanip>
    #include <map>
    
    #define sc scanf
    #define pf printf
    #define REP(i,a,b) for(int i=(a);i<(b);i++)
    #define CLR(x,m) memset(x,m,sizeof x);
    #define LOCAL freopen("test.txt","r",stdin)
    #define UCCU ios::sync_with_stdio(0);
    #define XSD(i) cout << fixed << setprecision(i);
    #define pii pair<int,int>
    #define xx first
    #define yy second
    
    using namespace std;
    
    typedef long long LL;
    typedef double DB;
    
    const double eps = 1e-6;
    const int maxn = 400100;
    
    map<int,int> mp,mp2;
    map<int, int> :: iterator it;
    pii a[maxn];
    int b[maxn];
    LL fen[maxn];
    
    void add(int n, int k)
    {
        for(; n < maxn; n += n & (-n))
          fen[n] += k;
    }
    
    int get(int n)
    {
        int res = 0;
        for(; n > 0; n -= n & (-n))
          res += fen[n];
        return res;
    }
    
    
    void run()
    {
        int n;
        cin>>n;
        REP(i,0,n){
            int u,v;cin>>u>>v;
            if(!mp[u]) mp[u]=u;
            if(!mp[v]) mp[v]=v;
            int temp = mp[u];
            mp[u] = mp[v];
            mp[v] = temp;
        }
    
        int pre=1,num=0;
        for(it = mp.begin();it!=mp.end();++it){
            int x = (*it).xx;int y = (*it).yy;
            if(x!=1&&x-pre-1){
                a[++num]=pii(x-1,x-pre-1);
                b[num]=x-1;
            }
            a[++num]=pii(y,1);
            b[num]=y;
            pre=x;
        }
    
    
        sort (b + 1, b + 1 + num);
        for (int i = 1; i <= num; i++) {
            mp2[b[i]] = i;
        }
        for (int i = 1; i <= num; i++) {
            a[i].xx = mp2[a[i].xx];
        }
    
        LL ans =0,tot=0;
        REP(i,1,num+1){
            ans+=1LL * (tot-get(a[i].xx))*a[i].yy;
            add(a[i].xx,a[i].yy);
            tot+=a[i].yy;
        }
        cout<<ans<<endl;
    }
    
    int main()
    {
        //LOCAL;
        UCCU;//cin.tie();
        run();
        return 0;
    }
    View Code
  • 相关阅读:
    linux下的开源移动图像监测程序--motion编译与配置【转】
    motion程序的移植和安装【转】
    Android5.1 在init.rc 中添加自己的服务【转】
    Android进程回收机制LMK(Low Memory Killer)【转】
    Linux内核OOM机制的详细分析【转】
    Android——build.prop 解析【转】
    Android——build.prop 解析【转】
    【转】ios的控件UIScrollView的位置定位---------逐渐积累
    【转】IOS图像拉伸解决方案
    【转】NSString属性什么时候用copy,什么时候用strong?
  • 原文地址:https://www.cnblogs.com/BugClearlove/p/4471458.html
Copyright © 2011-2022 走看看