• POJ 2299 Ultra-QuickSort (求逆序数:离散化+树状数组或者归并排序求逆序数)


    Ultra-QuickSort
    Time Limit: 7000MS   Memory Limit: 65536K
    Total Submissions: 55048   Accepted: 20256

    Description

    In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by swapping two adjacent sequence elements until the sequence is sorted in ascending order. For the input sequence 
    9 1 0 5 4 ,

    Ultra-QuickSort produces the output 
    0 1 4 5 9 .

    Your task is to determine how many swap operations Ultra-QuickSort needs to perform in order to sort a given input sequence.

    Input

    The input contains several test cases. Every test case begins with a line that contains a single integer n < 500,000 -- the length of the input sequence. Each of the the following n lines contains a single integer 0 ≤ a[i] ≤ 999,999,999, the i-th input sequence element. Input is terminated by a sequence of length n = 0. This sequence must not be processed.

    Output

    For every input sequence, your program prints a single line containing an integer number op, the minimum number of swap operations necessary to sort the given input sequence.

    Sample Input

    5
    9
    1
    0
    5
    4
    3
    1
    2
    3
    0
    

    Sample Output

    6
    0
    题意:就是求逆序数
    分析:有几种方法,这里用了两个
    #include<stdio.h>
    #include<string.h>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    
    const int MAXN = 500010;
    int F[MAXN];
    int a[MAXN];
    int n;
    pair<int,int>p[MAXN];
    void update(int x,int val)
    {
        while(x<=n)
        {
            F[x]+=val;
            x+=x&-x;
        }
    }
    int query(int x)
    {
        int res=0;
        while(x>0)
        {
            res+=F[x];
            x-=x&-x;
        }
        return res;
    }
    
    int main()
    {
        while(scanf("%d",&n)==1&&n)
        {
            memset(F,0,sizeof(F));
            memset(a,0,sizeof(a));
            for(int i=1;i<=n;i++)
            {
                scanf("%d",&p[i].first);
                p[i].second=i;
            }
            sort(p+1,p+n+1);
            a[p[1].second]=1;
            for(int i=2;i<=n;i++)
            {
                if(p[i].first!=p[i-1].first) a[p[i].second]=i;
                else a[p[i].second]=a[p[i-1].second];
            }
            long long ans=0;
            for(int i=1;i<=n;i++)
            {
                update(a[i],1);
                ans+=query(n)-query(a[i]);
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
    /*
     用归并排序求逆序数
     */
    #include<stdio.h>
    #include<string.h>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    
    const int MAXN = 500010;
    int a[MAXN],b[MAXN],c[MAXN];
    long long ans;
    
    //将已经排好的l-mid,mid+1-r进行归并
    void merge(int *a,int l,int mid,int r)
    {
        for(int i=0,j=l;j<=mid;j++)
            b[i++]=a[j];
        int len1=mid-l+1;
        for(int i=0,j=mid+1;j<=r;j++)
            c[i++]=a[j];
        int len2=r-mid;
        int i=0,j=0,k=l;
        while(i<len1&&j<len2&&k<=r)
        {
            if(b[i]<=c[j]) a[k++]=b[i++];
            else
            {
                a[k++]=c[j++];
                ans+=len1-i;//逆序数就是累加后面比自己小的数的个数
                //此时b[i]>c[j],那么c[j]会给b[i]后面的len1-i个数造成逆序数
            }
        }
        while(i<len1) a[k++]=b[i++];
        while(j<len2) a[k++]=c[j++];
    }
    void merge_sort(int *a,int l,int r)
    {
        if(l<r)
        {
            int mid=(l+r)/2;
            merge_sort(a,l,mid);
            merge_sort(a,mid+1,r);
            merge(a,l,mid,r);
        }
    }
    
    int main()
    {
        int n;
        while(scanf("%d",&n)==1&&n)
        {
            for(int i=1;i<=n;i++)
                scanf("%d",&a[i]);
            ans=0;
            merge_sort(a,1,n);
            printf("%lld
    ",ans);
        }
        return 0;
    }
     
  • 相关阅读:
    2020/10/23-大族激光
    Windows权限维持总结
    了解蓝军--jsonhijack漏洞学习
    white-space、word-break、word-wrap傻傻分不清楚
    Vue其他指令(v-cloak和v-text,v-html,v-pre,v-once)
    Vue循环渲染(v-for)
    Vue条件渲染(v-if)
    Vue绑定事件监听器(v-on)
    Vue绑定数据和元素属性(v-bind)
    记录一下,破解idea
  • 原文地址:https://www.cnblogs.com/wangdongkai/p/5742647.html
Copyright © 2020-2023  润新知