HDU - 5775 Bubble Sort(树状数组)

来源:互联网 发布:鑫众棋牌源码 编辑:程序博客网 时间:2024/06/01 09:31

Bubble Sort

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 659    Accepted Submission(s): 393


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.
 
题意:给一个 1 - N 的排列,它经过冒泡排序(从后往前)恢复成正常的递增序列。问在冒泡的过程中,每个数字最左位置和最右位置的差的绝对值。

思路:仔细想一下会发现每个数字只会被它后面的比它小的数字影响,且会向右移动相应个数的位置。比如:6 4 3 5 2 1 。4后面比它小的有 三个,因此它的最右边位置就是当前位置 +3,即5。如果该数字本身在标准位置左边,那无须考虑,初始位置就是最左端,如果它在标准位置右边,我们可以知道,它最终肯定要回到标准位置,所以最左边应该为标准位置。


利用树状数组从后往前维护一下比当前位置小的元素个数,并插入树状数组即可。(每次插入前判断从 1 到 该数字 之间有没有数字,利用sum (i) 可以求得,之后再插入该数字即可,插到对应数字的位置)

代码:
#include <iostream>#include <cstring>using namespace std;int a[100005];int ans[100005];int c[100005];int lowbit(int x){    return x & (-x);}void add(int id,int p){    while(id <= 100000){        c[id] += p;        id += lowbit(id);    }}int sum(int id){    int sum = 0;    while(id >= 1){        sum += c[id];        id -= lowbit(id);    }    return sum;}int main(){    ios_base::sync_with_stdio(0);    cin.tie(0);    int T;    cin>>T;    int cnt = 0;    while(T--){        int n;        cin>>n;        memset(a,0,sizeof(a));        memset(ans,0,sizeof(ans));        memset(c,0,sizeof(c));        for(int i = 1;i <= n;i ++)  cin>>a[i];        for(int i = n;i >= 1;i --){            int res = sum(a[i]);        //判断比该数字小的区间内有多少数字            ans[a[i]] = res;            add(a[i],1);        //插入该数字到标准位置        }        for(int i = 1;i <= n;i ++)            if(i >= a[i])                ans[a[i]] += (i-a[i]);      //初始位置在标准位置右边,最左端为标准位置,更新|left - right|        cout<<"Case #"<<++cnt<<": ";        for(int i = 1;i <= n;i ++){            if(i != 1)  cout<<" ";            cout<<ans[i];        }        cout<<endl;    }    return 0;}



0 0