题目链接:
http://acm.hdu.edu.cn/contests/contest_showproblem.php?pid=1012&cid=707
题意:
给出一组数字,求第i个数字在冒泡排序中能走到的最左端与最右端位置的差的绝对值。
题解:
考虑一个位置上的数字c在冒泡排序过程的变化情况。c会被其后面比c小的数字各交换一次,之后c就会只向前移动。数组从右向左扫,树状数组维护一下得到每个值右边有多少个比其小的值,加上原位置得到最右位置,最左位置为初始位置和最终位置的最小值。
时间复杂度O(n\ lg\ n)O(n lg n)
总的来说树状数组搞一搞就好了
AC代码:
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
int tree[100500],n;
int lowbit(int i)
{
return i&( -i);
}
void add(int k, int i)
{
while(k <= n)
{
tree[k] += i;
k += lowbit(k);
}
}
int sum(int k)
{
int re = 0;
while(k > 0)
{
re += tree[k];
k -= lowbit(k);
}
return re;
}
int ans[100200];
int number[100050],number2[100050],nixu[100050];
int main()
{
int t,cnt = 1,bgin,ed;
cin >> t;
while(t--)
{
bgin = 0, ed = 0;
cin >> n;
for(int i = 1; i<= n; i++)
cin >> number2[i];
for(int i = n; i >= 1; i--)
{
number[n-i] = number2[i] - 1;
}
for(int i = 0; i < n; i ++)
{
nixu[n - i] = i - sum(n - number[i]);
add(n - number[i],1);
}
for(int i = 1; i <= n; i++)
{
ed = i + nixu[i];
bgin = min(i, number2[i]);
ans[number2[i]] = abs(bgin - ed);
}
cout << "Case #"<< cnt++ <<":";
for(int i = 1; i <= n;i ++)
cout << " " <<ans[i];
cout << endl;
memset(tree,0,sizeof(tree));
}
return 0;
}