• POJ-2299 Ultra_QuickSort 线段树+逆序对数


    Ultra-QuickSort
    Time Limit: 7000MS Memory Limit: 65536K
    Total Submissions: 50737 Accepted: 18595

    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

    Source
    Waterloo local 2005.02.05

    题目大意:给定一个数列,求冒泡排序交换次数(逆序对数)

    线段树求逆序对,在数据范围过大的时候,需要进行离散化,然后进行建树,基本题
    

    代码:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    #define maxn 500002
    int sum[maxn<<2]={0};
    struct data{
        int num,loc;
    };
    int f2[maxn]={0};
    data f1[maxn]={0};
    
    int cmp(data x,data y)
    {
        return x.num<y.num;
    }
    
    void updata(int now)
    {
        sum[now]=sum[now<<1]+sum[now<<1|1];
    }
    
    void point_change(int now,int l,int r,int loc)
    {
        if (l==r)
            {
                sum[now]++;
                return;
            }
        int mid=(l+r)>>1;
        if (loc<=mid)
            point_change(now<<1,l,mid,loc);
        else
            point_change(now<<1|1,mid+1,r,loc);
        updata(now);
    }
    
    int query(int L,int R,int l,int r,int now)
    {
        if (L<=l && R>=r)
            return sum[now];
        int mid=(l+r)>>1;
        int ans=0;
        if (L<=mid)
            ans+=query(L,R,l,mid,now<<1);
        if (R>mid)
            ans+=query(L,R,mid+1,r,now<<1|1);
        return ans;
    }
    
    int main()
    {
        int n;
        while (true)
            {
                scanf("%d",&n);
                memset(f1,0,sizeof(f1));
                memset(f2,0,sizeof(f2));
                memset(sum,0,sizeof(sum));
                if (n==0) break;
                long long number=0;
                for (int i=1; i<=n; i++)
                        {
                            scanf("%d",&f1[i].num);
                            f1[i].loc=i;
                        }
                sort(f1+1,f1+n+1,cmp);
                for (int i=1; i<=n; i++)
                    f2[f1[i].loc]=i;//离散化部分(感觉这个离散化写的巨不专业) 
                //for (int i=1; i<=n; i++)
                    //cout<<f2[i]<<' ';
                //cout<<endl;
                for (int i=1; i<=n; i++)
                    {
                        int x=f2[i];
                        number+=query(x,n,1,n,1);
                        point_change(1,1,n,x);
                    }//逆序对的求法,每次从这个数到n求和,找出比他大的且出现在它之前的 
                printf("%d",number);
            }
        return 0;
    }
  • 相关阅读:
    UVA 11021繁衍模型+概率计算
    LA 5059博弈+SG函数
    LA 3942 字典树
    Beat---hdu2614
    Wooden Sticks---hdu1051(最长上升子序列)
    欧拉函数基础
    1370
    钱币兑换问题---hdu1284(完全背包)
    Drainage Ditches--hdu1532(网络流 模板)
    Fibonacci--poj3070(矩阵快速幂)
  • 原文地址:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5346254.html
Copyright © 2020-2023  润新知