zoukankan      html  css  js  c++  java
  • HDU-1394 Minimum Inversion Number

    Problem Description
    The inversion number of a given number sequence a1, a2, …, an is the number of pairs (ai, aj) that satisfy i < j and ai > aj.
    For a given sequence of numbers a1, a2, …, an, if we move the first m >= 0 numbers to the end of the seqence, we will obtain another sequence. There are totally n such sequences as the following:
    a1, a2, …, an-1, an (where m = 0 - the initial seqence)
    a2, a3, …, an, a1 (where m = 1)
    a3, a4, …, an, a1, a2 (where m = 2)

    an, a1, a2, …, an-1 (where m = n-1)
    You are asked to write a program to find the minimum inversion number out of the above sequences.

    Input
    The input consists of a number of test cases. Each case consists of two lines: the first line contains a positive integer n (n <= 5000); the next line contains a permutation of the n integers from 0 to n-1.

    Output
    For each case, output the minimum inversion number on a single line.

    Sample Input
    10
    1 3 6 9 0 8 5 7 4 2

    Sample Output
    16

    题意:
    题意:0~n-1且不一定有序排列的数字串,不断的将第一个数字放到数字串的最后,可以得到n个不同的数字串。每一个数字串都有一个逆序数,求n个数字串中最小的逆序数。
    思路:
    很简单的线段树,树状数组也可以做,把数拿下来每次往线段树里面查,或者往一个新数组里面插,就xjb些就行了

    做这道题的时候初识线段树,竟然敲了一大段代码手写了一个for循环,坑爹的是竟然 842Ms 水过了
    后来for循环写了一下 102Ms就过了 —– 菜鸡如我
    仔细学习了一下线段树之后理解了线段树的区间查询再写了一次 42 Ms 过了 在这里写一下心得体会,
    线段树的区间查询操作之所以是O(lg(n))的复杂度,完全是因为分治,每次都查询一半,如果每一个都遍历一次的话,
    跟for循环就一模一样了,而且百度学习线段树的时候还学习到了懒标记的使用,也是线段树的一大重点,能够很好的降低时间复杂度,值得学习

    ———————————————————-AC code—————————————

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    #define lson l,mid,rt<<1
    #define rson mid+1,r,rt<<1|1
    using namespace std;
    const int maxn = 6000+5;
    struct segtree{
        int l,r;
        int sum;
    }ss[maxn<<2];
    
    int v[maxn];
    
    void build(int l,int r,int rt ) {
        ss[rt].l = l,ss[rt].r = r;
        if ( ss[rt].l == ss[rt].r ) { ss[rt].sum = 0; return;}
        int mid = (l+r)>>1;
        build(lson); build(rson);
        ss[rt].sum = 0;
    }
    
    void update(int l,int r,int rt){
        if ( ss[rt].l == ss[rt].r ) { ss[rt].sum++; return; }
        int mid = (ss[rt].l+ss[rt].r)>>1;
        if ( mid >= r ) update(l,r,rt<<1);
        else update(l,r,rt<<1|1);
        ss[rt].sum = ss[rt<<1].sum + ss[rt<<1|1].sum;
    }
    
    int query(int l,int r,int rt){
        if ( ss[rt].l == l && ss[rt].r == r ){
            return ss[rt].sum;
        }
        int mid = (ss[rt].l+ss[rt].r)>>1; int s = 0;
        if ( mid >= r ) {
            s += query(l,r,rt<<1);
        } else if ( mid < l ) {
            s += query(l,r,rt<<1|1);
        } else {
            s += query(l,mid,rt<<1);
            s += query(mid+1,r,rt<<1|1);
        }
        return s;
    }
    
    int main(){
        int t;
        while(~scanf("%d",&t)){
            build(1,t,1);
            int sum = 0;
            for (int i = 1;i<=t;i++) {
                scanf("%d",&v[i]); v[i]++;
                if ( v[i] != t )
                    sum += query(v[i]+1,t,1);
                update(v[i],v[i],1);
            }
            int minn = sum;
            for (int i = 1;i<=t;i++){
                sum = sum + t - 2*v[i] + 1;
                minn = min(minn,sum);
            }
            printf("%d
    ",minn);
        }
        return 0;
    }
    

    其实树状数组也可以实现

    ——————————————- AC code ————————————————-

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define debug puts("ok!");
    using namespace std;
    //typedef long long ll;
    const int maxn = 50000+5;
    
    int bit[maxn],t;
    
    int lowbit(int pos){
        return (pos & (-pos));
    }
    int query(int pos){
        int ret = 0;
        while(pos > 0){
            ret += bit[pos];
            pos -= lowbit(pos);
        }
        return ret;
    }
    void update(int pos)
    {
        while(pos<=t){
            bit[pos] ++;
            pos += lowbit(pos);
        }
    } 
    
    int v[maxn];
    
    int main(){
        while(cin>>t){
            int sum = 0;
            memset(bit,0,sizeof(bit));
            for (int i = 1;i<=t;i++) {
                scanf("%d",&v[i]);    v[i]++;
                sum += query(t) - query(v[i]);
                //printf("%d
    ",query(t));
                update(v[i]);
            }
            //printf("%d
    ",sum);
            int minn = sum;
            for (int i = 1;i<=t;i++){
                sum = sum + t - 2*v[i] + 1;
                minn = min(minn,sum);
            }
            printf("%d
    ",minn);
        }
        return 0;
    } 
  • 相关阅读:
    C# 不用添加WebService引用,调用WebService方法
    贪心 & 动态规划
    trie树 讲解 (转载)
    poj 2151 Check the difficulty of problems (检查问题的难度)
    poj 2513 Colored Sticks 彩色棒
    poj1442 Black Box 栈和优先队列
    啦啦啦
    poj 1265 Area(pick定理)
    poj 2418 Hardwood Species (trie树)
    poj 1836 Alignment 排队
  • 原文地址:https://www.cnblogs.com/Nlifea/p/11745976.html
Copyright © 2011-2022 走看看