• Ultra-QuickSort(树状数组求逆序对数)


    Ultra-QuickSort
    Time Limit: 7000MS   Memory Limit: 65536K
    Total Submissions: 51641   Accepted: 18948

    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
    题解:树状数组求逆序对数,就是求对于每一个数后面有多少个数字比它自己的数字小,那么从后向前遍历所有的数字,a[x]表示的是当前状态下小于等于x的值得个数.那么从后往前的扫描所有的数值统计后,再把这个数字对应的a[x]++;这样在扫描它前面的数的时候就相当于考虑这个数了,这种总是求a的前缀和和对单独点修改的操作可以使用树状数组解决。
    注意这个题要解决的数很大,所以要离散化一下,这里介绍两种离散化的方法:
    1.写一个二分查找的函数,先sort()一下,然后对于每个值,find(x)返回的下标值就是离散化后的结果,这里注意因为树状数组不能处理下标是0的情况,所以要将编号从1开始。而且要注意结果有可能会超int所以要用long long ,因为这个wa了好多次。
    代码:
     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 #define ll long long
     6 const ll N = 500005;
     7 ll a[N];
     8 ll mp[N];
     9 ll tree[N];
    10 ll lowbit(ll x){
    11     return x&(-x);
    12 }
    13 ll sum(ll x){
    14     ll ans = 0;
    15     while(x > 0){
    16         ans += tree[x];
    17         x-=lowbit(x);
    18     }
    19     return ans;
    20 }
    21 void add(ll x){
    22     while(x<=N){
    23         tree[x]++;
    24         x+=lowbit(x);
    25     }
    26 }
    27 ll n;
    28 ll find(ll x){
    29     ll l = 0;
    30     ll r = n-1;
    31     ll mid = (l+r)/2;
    32     while(l<=r){
    33         if(a[mid]==x) return mid;
    34         else if(a[mid]<x) l = mid+1;
    35         else if(a[mid]>x) r = mid-1;
    36         mid = (l+r)/2;
    37     }
    38 }
    39 int main()
    40 {
    41     while(~scanf("%d",&n))
    42     {
    43         if(n==0) return 0;
    44         memset(tree,0,sizeof(tree));
    45         for(ll i = 0; i < n; i++){
    46             scanf("%I64d",&mp[i]);
    47             a[i] = mp[i];
    48         }
    49         sort(a,a+n);
    50         ll ans = 0;
    51         for(ll i = n-1; i >= 0; i--){//从后往前扫描
    52             mp[i] = find(mp[i])+1;
    53             //prllf("%d 
    ",mp[i]);
    54             ans += sum(mp[i]-1);
    55             //prllf("ans = %d ",ans);
    56             add(mp[i]);
    57         }
    58         printf("%I64d
    ",ans);
    59     }
    60     return 0;
    61 }
     
  • 相关阅读:
    Firefox页面截图插件Pearl Crescent Page Saver
    Effective C++ (5) 几个关于数组的问题
    Notice
    Effective C++ (4) c++中的命名空间
    Effective C++ (7) 强制类型转换
    Effective C++ (3) 避免C++头文件的多重包含
    Effective C++ (2) C#中的Const和Readonly
    总结一下这段时间的生活
    如何让rose一开始的那个向导对话框出现?
    Effective C++ (8) 顺序容器vector,list,deque
  • 原文地址:https://www.cnblogs.com/shanyr/p/5217134.html
Copyright © 2020-2023  润新知