您的位置:首页 > 产品设计 > UI/UE

poj 2299 Ultra-QuickSort

2013-11-16 21:04 267 查看
本题就是求逆序数,在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数
令t[i]表示逆序对(a[j],i)的个数,即排在i的左边且比i大的数的个数,则逆序数为t[1]+t[2]+···t

例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
的逆序数,num = t[1]+t[2]+·····+t
;


算法:

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



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: