poj2299Ultra-QuickSort【线段树求逆序数】离散化

Ultra-QuickSort
Time Limit: 7000MS   Memory Limit: 65536K
Total Submissions: 52097   Accepted: 19113

Description

poj2299Ultra-QuickSort【线段树求逆序数】离散化_第1张图片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

之前写过求逆序数的树状数组的方法和归并排序的方法

poj2299Ultra-QuickSort【树状数组求逆序数、离散化】、【归并排序模板】

感觉逆序数这玩意就应该用归并排序做啊~~

说线段树的方法:与上一篇

poj2352Stars【线段树单点更新区间求和】

相似的是,都是单点更新区间求和,而且从自身到根节点这一路一直++。不同的是,之前那个题是求前一部分的和,这个要求后一部分的值,这我就不理解了,逆序数明明等于N-[1,i]的值啊,为啥查询的时候只需要求[i+1,n]?好好想想:区间[1,i]的值+区间[i+1,N]的值=区间[1,N]的值(i已经标记为1),所以区间[i+1,N]值的总和等于N-[1,i]的值!因为总共有N个数,不是比它小就是比它(大或等于)。……

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 500005
struct node
{
    int id,val;
}num[maxn];
bool cmp(node n1,node n2)
{
    return n1.val<n2.val;
}
struct Tree
{
    int l,r,tot;
}tree[maxn<<2];
int rank[maxn];
void build(int rt,int l,int r)
{
    tree[rt].l=l;tree[rt].r=r;
    tree[rt].tot=0;
    if(l==r)return;
    int mid=(l+r)/2;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid+1,r);
}
void update(int rt,int x)
{
    tree[rt].tot++;
    if(tree[rt].l==tree[rt].r&&tree[rt].l==x)
        return;
    int mid=(tree[rt].l+tree[rt].r)/2;
    if(x<=mid)update(rt<<1,x);
    else update(rt<<1|1,x);
}
int query(int rt,int l,int r)
{
    int sum=0;
    if(tree[rt].l==l&&tree[rt].r==r)
        return tree[rt].tot;
    int mid=(tree[rt].l+tree[rt].r)/2;
    if(r<=mid) sum=query(rt<<1,l,r);
    else if(l>mid) sum=query(rt<<1|1,l,r);
    else
        sum=query(rt<<1,l,mid)+query(rt<<1|1,mid+1,r);
    return sum;
}
int main()
{
   // freopen("cin.txt","r",stdin);
    int n;
    while(~scanf("%d",&n)&&n)
    {
        for(int i=0;i<n;i++)
        {
            scanf("%d",&num[i].val);
            num[i].id=i;
        }
        sort(num,num+n,cmp);
        for(int i=0;i<n;i++) rank[num[i].id]=i+1;
        build(1,0,n+1);
        long long sum=0;
        for(int i=0;i<n;i++)
        {
            int x = rank[i];
            sum+=query(1,x+1,n+1);
            update(1,x);
        }
        printf("%I64d\n",sum);
    }
    return 0;
}


你可能感兴趣的:(线段树,poj)