poj 2299 Ultra-QuickSort

    本题就是求逆序数,在一个排列中,如果一对数的前后位置与大小 顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数

    令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;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值