HDU5775Bubble Sort(树状数组)

来源:互联网 发布:iphone视频调色软件 编辑:程序博客网 时间:2024/06/05 04:40

Problem Description
P is a permutation of the integers from 1 to N(index starting from 1).
Here is the code of Bubble Sort in C++.
for(int i=1;i<=N;++i)    for(int j=N,t;j>i;—j)        if(P[j-1] > P[j])            t=P[j],P[j]=P[j-1],P[j-1]=t;

After the sort, the array is in increasing order. ?? wants to know the absolute values of difference of rightmost place and leftmost place for every number it reached.
 

Input
The first line of the input gives the number of test cases T; T test cases follow.
Each consists of one line with one integer N, followed by another line with a permutation of the integers from 1 to N, inclusive.

limits
T <= 20
1 <= N <= 100000
N is larger than 10000 in only one case. 
 

Output
For each test case output “Case #x: y1 y2 … yN” (without quotes), where x is the test case number (starting from 1), and yi is the difference of rightmost place and leftmost place of number i.
 

Sample Input
233 1 231 2 3
 

Sample Output
Case #1: 1 1 2Case #2: 0 0 0
Hint
In first case, (3, 1, 2) -> (3, 1, 2) -> (1, 3, 2) -> (1, 2, 3)the leftmost place and rightmost place of 1 is 1 and 2, 2 is 2 and 3, 3 is 1 and 3In second case, the array has already in increasing order. So the answer of every number is 0.


题意:求每个数在上述的冒泡排序中能够达到的最左端和最右端的差值。

分析:题目给出的冒泡排序是把小的数不断往前挪,如果一个数后面有比它小的数,那么它肯定会因为那个小的数的移动到它左边而使自己的位置往右移动一位。

你可以发现一个规律这个数右边有几个小于它的数,这个数就会向右移动几位。如果一个数在它本来应该在的位置的左端,那么直需要统计右边比它小的个数即可,因为冒泡排序使它回归到正确位置之后,它左边的数肯定都是比它小的了,它不会再移动到它正确位置的右边。(理解题目给的冒泡代码)如果一个数在它应该在的位置的右边,那么就需要求它右边比它小的数的个数以及它离正确位置的距离之和。

看这么一组例子

5

4 3 2 1 5

冒泡过程:

4 3 2 1 5

->1 4 3 2 5

-> 1 2 4 3 5

->1 2 3 4 5

可以看到在第一次排序的时候,即1 4 3 2 5中的2没有往左边走,反而因为之前1的存在而使得自己往右走了一位,这个便是它能够达到的最右位置,然而它正确的位置离它现在的位置却是2,,所以可以看到这时候是会有“负效应”的。

特别需要记住的是:如果冒泡排序的前m个数已经排好了, 那么再后面的冒泡过程中就不会再有数插入到前m个数中去。

#include<iostream>#include<algorithm>#include<cstring>#include<cstdio>using namespace std;const int maxn = 100005;int C[maxn], cou[maxn], a[maxn];int lowbit(int lo){    return lo & (-lo);}void modify(int pos, int value){    while(pos < maxn)    {        C[pos] += value;        pos += lowbit(pos);    }}int getsum(int pos){    int sum = 0;    while(pos > 0)    {        sum += C[pos];        pos -= lowbit(pos);    }    return sum;}int main(){    int T, n;    scanf("%d", &T);    for(int t = 1; t <= T; t++)    {        scanf("%d", &n);        memset(C, 0, sizeof(C));        memset(cou, 0, sizeof(cou));        for(int i = 1; i <= n; i++)            scanf("%d", &a[i]);        for(int i = n; i >= 1; i--)        {            int sum = getsum(a[i]);            modify(a[i], 1);            cou[a[i]] = sum;            if(i > a[i])                cou[a[i]] += (i - a[i]);        }        printf("Case #%d: ", t);        for(int i = 1; i < n; i++)            printf("%d ", cou[i]);        printf("%d\n", cou[n]);    }    return 0;}


0 0