• poj 2299 , 线段树


    Ultra-QuickSort
    Time Limit: 7000MS   Memory Limit: 65536K
    Total Submissions: 35702   Accepted: 12856

    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

     
    归并排序,线段树都可以,这是线段树版本,参考了网上题解,另外抄下我看懂了的解答
    (来自 :http://zhidao.baidu.com/link?url=aqpEDgNFTQkoM4X9ebJMV-DpXoJvE5L8p9P3S-ysVJpUX_qBNdG99pHU00pOodYtMlNDKBiSkiIwc61ROroHbq )
     
    “很简单……
    设数列为a,将数列离散化,在从前往后枚举,统计答案……
    离散化:例如2 5 8 3 10 等价于 1 3 4 2 5,可以通过排序加小小处理解决。
    枚举到第i个数,我们需要求出从1到i-1中有多少个比a[i]大的数,更新答案。
    具体怎么做呢?
    每次枚举完一个数之后,将这个数插入到线段树里,插入到线段树的神马地方呢?当然是这个数多大就插入到多大的地方。
    举个例子:3 2 4 1。则线段树的变化应该为:tree[3]+=1;tree[2]+=1;tree[4]+=1;tree[1]+=1;
    设x=a[i],这样,在插入一个数X时,首先求一下tree[x+1]~tree[n]的和,这个和就是1~i-1中有多少个比a[i]大的数。运用线段树求和可以做到O(n log n)吧,具体实现我就不再赘述了。”
     
    我的AC代码(用map会TLE。。。):
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<set>
    #include<queue>
    #include<string>
    #include<cmath>
    #include<fstream>
    #include<iomanip>
    #include<map>
    
    using namespace std;
    
    #define LL long long
    
    #define MAXN 500005
    #define lson rt<<1, l, m
    #define rson rt<<1|1, m, r
    
    int n, sum[MAXN<<2];
    
    int query(int rt, int l, int r, int cl, int cr){
        if(cl<=l && cr>=r) return sum[rt];
    
        int ret = 0;
        int m = l + r >> 1;
        if(cl < m) ret += query(lson, cl, cr);
        if(cr > m) ret += query(rson, cl, cr);
        return ret;
    }
    
    void update(int rt, int l, int r, int x){
        if(l+1 == r){
            sum[rt]++;  return;
        }
        int m = l + r >> 1;
        if(x < m) update(lson, x);
        else update(rson, x);
        sum[rt] = sum[rt<<1] + sum[rt<<1|1];
    }
    
    struct node{
        int val, id;
        bool operator <(const node &rhs)const{
            return val < rhs.val;
        }
    }t[MAXN];
    int rank[MAXN];
    
    int main(){
    //    freopen("C:\Users\Administrator\Desktop\in.txt","r",stdin);
        while(scanf(" %d", &n)==1 && n){
            for(int i=0; i<n; i++)
                scanf(" %d", &t[i].val), t[i].id=i;
            sort(t, t+n);
            fill_n(sum+1, n<<2, 0);
            for(int i=0; i<n; i++) rank[t[i].id]=i+1;
            LL ans = 0;
    
            for(int i=0; i<n; i++){
                int t = rank[i];
                ans += query(1, 1, 1+n, t, 1+n);
                update(1, 1, 1+n, t);
            }
            printf("%lld
    ", ans);
        }
        return 0;
    }
    

    归并排序

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    
    using namespace std;
    
    const int maxn = 500005;
    int a[maxn], sub[maxn];
    long long cnt;
    
    void merg(int *a, int n){
        int *b= a + (n>>1), n1 = n>>1, n2 = n-n1;
        for(int i=0, j=0, k=0; i<n1 || j<n2; ){
            if(i<n1 && j<n2){
                if(a[i]>b[j]) sub[k++] = b[j++], cnt += n1-i;
                else sub[k++] = a[i++];
            }
            else if(i<n1) sub[k++] = a[i++];
            else sub[k++] = b[j++];
        }
        memcpy(a, sub, n*sizeof(int));
    }
    
    void mergesort(int *a, int n){
        if(n<2) return;
        mergesort(a, n>>1);
        mergesort(a+(n>>1), n-(n>>1));
        merg(a, n);
    }
    
    int main(){
        int n;
        while(scanf(" %d", &n)==1 && n){
            for(int i=0; i<n; i++) scanf(" %d", a+i);
            cnt = 0;
            mergesort(a, n);
            printf("%lld
    ", cnt);
        }
        return 0;
    }
    
  • 相关阅读:
    linux之用户和用户组管理详解
    linux权限管理
    flink 1.7.2 安装详解
    TJI读书笔记13-内部类
    TJI读书笔记12-接口
    TJI读书笔记11-多态
    TJI读书笔记10-复用类
    TJI读书笔记09-访问控制权限
    TIJ读书笔记08-数组的初始化和可变长参数形参
    TJI读书笔记07-初始化
  • 原文地址:https://www.cnblogs.com/ramanujan/p/3391363.html
Copyright © 2020-2023  润新知