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\n", 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\n", cnt);
    }
    return 0;
}

 

posted @ 2013-10-27 22:44  Ramanujan  阅读(238)  评论(0编辑  收藏  举报