POJ 2299 Ultra-QuickSort

来源:互联网 发布:决战武林神兵进阶数据 编辑:程序博客网 时间:2024/04/26 14:20

这个题目的本质是求一个数组的逆序对的数量,在线性代数里面一个求逆序对数量的方法是,每次取所有剩余数字当中最小的数,然后数一数这个数前面有多少已经取出来的数字,即为当前这个数字所贡献的逆序数,所以本题就要模拟这个过程,排序之后每次取出最小的数然后开始数

但是直接的模拟会导致超时,因此采用树状数组对已经取出来的点的个数进行记录,每次求和然后更新

注意用long long 存储最后的答案

#include <iostream>#include <memory.h>#include <cstdio>#include <algorithm>using namespace std;#define maxn 500050struct node{    int key,pos;};bool operator < (node a, node b){    return a.key < b.key;}node array[maxn]={0};int inter[maxn]={0};long long int getsum(int i){    long long sum = 0;    for(;i>0;i-=i&(-i)){        sum += inter[i];    }     return sum;}void update(int i,int n){    for(;i<=n;i+=i&(-i)){        inter[i]++;    }}int main(){    int n;    while(scanf("%d",&n),n){        long long int sum = 0;        memset(array,0,sizeof(array));        memset(inter,0,sizeof(inter));        for(int i=1;i<=n;++i){            scanf("%d",&array[i].key);            array[i].pos = i;        }        sort(array+1,array+n+1);        for(int i=n;i>0;--i){            sum += getsum(array[i].pos);            update(array[i].pos,n);        }         printf("%lld\n",sum);    }    return 0;}
0 0