• POJ2299(离散化树状数组)


    Ultra-QuickSort
    Time Limit: 7000MS   Memory Limit: 65536K
    Total Submissions: 51852   Accepted: 19039

    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

    总觉得有什么知识点忘记了想还想不起来,终于想到啦,哈哈。这道题的离散化思想在别的题上用到才给我这个提醒想到。
    /*此题的第一个技巧是把很大的数HASH成小的范围,第二个是把数组中数字的在对应排完序数组的位置定位。如这道题最后d[i]=j,表示的是第i个数是这些数字中第j小的数。
    实现第二个技巧需要明白HASH后的数组储存的是
    b:第下标小的数在第储存数的位,而我想知道的是第一位是第几小的数,用D数组从中取出来就行了,从1~N取就会出现d[3]中放置的为1,与b的下标相对应。完成了每一位储存的是第几小的数。
    此题的逆序数的算法也很巧妙,先把数组清零,把第一个数在的大小位置放进去,检查之前的大小位置放置了多少个数,就是他之前有多少比他小的数,那他之前就有i-[]个逆序数,
    有多少个数与标准顺序不同就有多少个逆序数。*/
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    const int N=500005;
    int n;
    int b[N],c[N],d[N];//
    int cmp(int x,int y){
        return c[x]<c[y];
    }
    int lowbit(int x){
        return x&(-x);
    }
    void add(int i,int w){
        while(i<=n){
            c[i]+=w;
            i+=lowbit(i);
        }
    }
    int sum(int i){
        int s=0;
        while(i){
            s+=c[i];
            i-=lowbit(i);
          //  printf("s=%d ",s);
        }
       // printf("
    ");
        return s;
    }
    int main(){
        while(scanf("%d",&n)!=EOF&&n){
            for(int i=1;i<=n;i++){
                scanf("%d",&c[i]);
                b[i]=i;
            }
            sort(b+1,b+1+n,cmp);//神奇的哈希大法,使用时间来换取空间,此时b[i]里储存的数字是才c里对应的下标的是的几小的数。b[1]=3表示才第三个数是第一小的。
            memset(c,0,sizeof(c));//此时c已经没有用了,清零方便后续使用
            for(int i=1;i<=n;i++){
                d[b[i]]=i;//把b中储存的数字取出来,赋值给的d数组,这用与之对应,d[3]=1,表示第三个数是第一小的数。至此数据的处理完成,(不过我也没看出来是二维的树状数组啊)。
            }
            long long ans=0;
           // for(int i=1;i<=n;i++) printf("%d ",c[i]);
            for(int i=1;i<=n;i++){
                add(d[i],1);
                int s=sum(d[i]);
    
                printf("%d-->%d
    ",d[i],i-s);
                ans+=i-s;
            }
            printf("%I64d
    ",ans);
        }
    }

    代码肯定是不会AC的因为我中间输出了检验过程,但思路很重要啊,只要看会了我写的思路,改成AC代码很简单。

  • 相关阅读:
    在javascript中如何取消事件冒泡
    ThinkPHP与EasyUI整合之二(datagrid):删除多条记录
    Jquery动画效果地铁站名指示等效果
    ubuntu 10.4 setup vm tools log
    Windows下Critical Section、Event、Mutex、Semaphores区别
    联通GPRS卡在windows mobile操作系统手机上网如何设置
    hope DATA
    电动车电池正确的使用方法
    C语言运算符表
    深圳市职业技能鉴定报名
  • 原文地址:https://www.cnblogs.com/VectorLin/p/5263190.html
Copyright © 2020-2023  润新知