poj 2299 Ultra-QuickSort

来源:互联网 发布:网络推广办法 编辑:程序博客网 时间:2024/06/06 03:16
    本题就是求逆序数,在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数

    令t[i]表示逆序对(a[j],i)的个数,即排在i的左边且比i大的数的个数,则逆序数为t[1]+t[2]+···t[n]   

    例l设n=8,a={3,2,l,5,8,4,6,7},t[1] = 2 ,t[2] = 1,t[3] = 0,t[4] = 1,t[5] = 0,t[6] = t[7] = 1,t[8] = 0;

    数状数组计算逆序数:计算a[1]+a[2]+a[3]····+a[n]的逆序数,num = t[1]+t[2]+·····+t[n];

算法:

   

sum = 0;for(i = l; i <= n; ++i)     b[a[i]] = i;for(i = 1; i <= n; ++i)     c[i] = 0;for(x = n; x>=l; --x){     p=b[x];     sum += Querry(p);     UFset(p, 1);}//本题代码:
#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>using namespace std;const int MAXN = 500010;int c[MAXN];struct Node{     int seq, val;}s[MAXN];int lowbit(int x){     return x & (-x);}void UFset(int pos, int data){     while(pos < MAXN)     {          c[pos] += data;          pos += lowbit( pos );     }}__int64 Querry(int pos){     __int64 sum = 0;     while(pos > 0)     {          sum += c[pos];          pos -= lowbit( pos );     }     return sum;}bool cmp(Node a, Node b){     return a.val < b.val;}int main(){     int n;     int b[MAXN];     while(scanf("%d", &n) != EOF && n)     {          for(int i = 1;i <= n; ++i)          {               scanf("%d",&s[i].val);               s[i].seq = i;          }          memset(c, 0, sizeof(c));          memset(b, 0, sizeof(b));          sort(s+1, s+1+n, cmp);          for(int i = 1; i <= n; ++i)               b[ s[i].seq ] = i;          __int64 sum = 0;          for(int i = n; i  >= 1; --i)          {               sum += Querry( b[i] );               UFset(b[i], 1);          }          printf("%I64d\n", sum);     }    return 0;}

	
				
		
原创粉丝点击